diff --git a/robohive/envs/arms/__init__.py b/robohive/envs/arms/__init__.py
index e9f1dfb0..f8714fed 100644
--- a/robohive/envs/arms/__init__.py
+++ b/robohive/envs/arms/__init__.py
@@ -76,7 +76,7 @@ def register_visual_envs(encoder_type):
'robot_site_name': "end_effector",
'object_site_name': "sugarbox",
'target_site_name': "target",
- 'target_xyz_range': {'high':[-.4, 0.5, 0.78], 'low':[-.4, 0.5, 0.78]}
+ 'target_xyz_range': {'high':[0.5, 0.4, 0.78], 'low':[0.5, 0.4, 0.78]}
}
)
@@ -91,10 +91,274 @@ def register_visual_envs(encoder_type):
'robot_site_name': "end_effector",
'object_site_name': "sugarbox",
'target_site_name': "target",
- 'target_xyz_range': {'high':[0.4, 0.5, 0.78], 'low':[-.4, .4, 0.78]}
+ 'target_xyz_range': {'high':[0.5, 0.4, 0.78], 'low':[0.4, -0.4, 0.78]}
}
)
+register(
+ # Init position: [0.51,0.23,0.98]
+ # Init euler: [-np.pi/4+0.3, np.pi+0.3, -3*np.pi/4,]
+ id='FrankaBinPush-v0',
+ entry_point='robohive.envs.arms.push_base_v0:PushBaseV0',
+ max_episode_steps=50, #50steps*40Skip*2ms = 4s
+ kwargs={
+ 'model_path': curr_dir+'/franka/assets/franka_bin_push_v0.xml',
+ 'config_path': curr_dir+'/franka/assets/franka_bin_push_v0.config',
+ 'robot_site_name': "end_effector",
+ 'object_site_name': "obj0",
+ 'obj_pos_limits': {'high':[0.52, 0.126, 0.955], 'low':[0.48, 0.125, 0.945]},
+ 'target_site_name': "target",
+ 'target_xyz_range': {'high':[0.5, -0.22, 1.085], 'low':[0.5, -0.22, 1.085]},
+ 'pos_limits': {'eef_low': [0.315, -0.3, 0.89, -0.485, 3.14, -2.36, 0.4],
+ 'eef_high': [0.695, 0.275, 1.175, -0.485, 3.14, -2.36, 0.4]
+ },
+ 'vel_limits': {'eef':[0.15, 0.15, 0.15],
+ 'jnt': [0.15, 0.25, 0.1, 0.25, 0.1, 0.25, 0.2, 1.0]
+ },
+ 'init_qpos': [0.534, 0.401, 0.0, -1.971, -0.457, 0.490, 1.617, 0.4, 0.4],
+ }
+)
+
+register(
+ # Init position: [0.51,0.23,0.98]
+ # Init euler: [-np.pi/4+0.3, np.pi+0.3, -3*np.pi/4,]
+ id='FrankaBinPushSmall-v0',
+ entry_point='robohive.envs.arms.push_base_v0:PushBaseV0',
+ max_episode_steps=50, #50steps*40Skip*2ms = 4s
+ kwargs={
+ 'model_path': curr_dir+'/franka/assets/franka_bin_push_v0.xml',
+ 'config_path': curr_dir+'/franka/assets/franka_bin_push_v0.config',
+ 'robot_site_name': "end_effector",
+ 'object_site_name': "obj0",
+ 'obj_pos_limits': {'high':[0.52, 0.126, 0.955], 'low':[0.48, 0.125, 0.945]},
+ 'target_site_name': "target",
+ 'target_xyz_range': {'high':[0.5, -0.22, 1.085], 'low':[0.5, -0.22, 1.085]},
+ 'pos_limits': {'eef_low': [0.315, -0.3, 0.89, -0.485, 3.14, -2.36, 0.4],
+ 'eef_high': [0.695, 0.275, 1.175, -0.485, 3.14, -2.36, 0.4]
+ },
+ 'vel_limits': {'eef':[0.15, 0.15, 0.15],
+ 'jnt': [0.15, 0.25, 0.1, 0.25, 0.1, 0.25, 0.2, 1.0]
+ },
+ 'init_qpos': [0.534, 0.401, 0.0, -1.971, -0.457, 0.490, 1.617, 0.4, 0.4],
+ }
+)
+
+register(
+ id='FrankaBinPushTeleop-v0',
+ entry_point='robohive.envs.arms.push_base_v0:PushBaseV0',
+ max_episode_steps=100, #50steps*40Skip*2ms = 4s
+ kwargs={
+ 'model_path': curr_dir+'/franka/assets/franka_bin_push_teleop_v0.xml',
+ 'config_path': curr_dir+'/franka/assets/franka_bin_push_v0.config',
+ 'robot_site_name': "end_effector",
+ 'object_site_name': "obj0",
+ 'obj_pos_limits': {'high':[0.52, 0.126, 0.955], 'low':[0.48, 0.125, 0.945]},
+ 'target_site_name': "target",
+ 'target_xyz_range': {'high':[0.22, 0.5, 1.02], 'low':[0.22, 0.5, 1.02]},
+ 'pos_limits': {'eef_low': [0.2, 0.05, 0.9, -0.485, 3.14, -2.36, 0.3507],
+ 'eef_high': [0.7, 0.6, 1.1, -0.485, 3.14, -2.36, 0.3507]
+ },
+ 'vel_limits': {'eef':[0.15, 0.15, 0.15],
+ 'jnt': [0.15, 0.25, 0.1, 0.25, 0.1, 0.25, 0.2, 1.0]
+ },
+ 'init_qpos': [0.767,0.492,-0.064,-1.965,-0.358,0.535,1.713,0.349,0.349],
+ }
+)
+
+register(
+ id='FrankaBinPushReal-v0',
+ entry_point='robohive.envs.arms.push_base_v0:PushBaseV0',
+ max_episode_steps=100, #50steps*40Skip*2ms = 4s
+ kwargs={
+ 'model_path': curr_dir+'/franka/assets/franka_bin_push_v0.xml',
+ 'config_path': curr_dir+'/franka/assets/franka_bin_push_v0.config',
+ 'robot_site_name': "end_effector",
+ 'object_site_name': "obj0",
+ 'obj_pos_limits': {'high':[0.52, 0.126, 0.955], 'low':[0.48, 0.125, 0.945]},
+ 'target_site_name': "target",
+ 'target_xyz_range': {'high':[0.22, 0.5, 1.02], 'low':[0.22, 0.5, 1.02]},
+ 'pos_limits': {'eef_low': [0.2, 0.05, 0.9, -0.485, 3.14, -2.36, 0.3507],
+ 'eef_high': [0.7, 0.6, 1.1, -0.485, 3.14, -2.36, 0.3507]
+ },
+ 'vel_limits': {'eef':[0.15, 0.15, 0.15],
+ 'jnt': [0.15, 0.25, 0.1, 0.25, 0.1, 0.25, 0.2, 1.0]
+ },
+ 'init_qpos': [0.767,0.492,-0.064,-1.965,-0.358,0.535,1.713,0.349,0.349],
+ }
+)
+
+register(
+ # Init position: [0.36, 0.0, 1.34]
+ # Init euler: [3.14, 0.5, -0.8,]
+ id='FrankaHangPush-v0',
+ entry_point='robohive.envs.arms.push_base_v0:PushBaseV0',
+ max_episode_steps=50, #50steps*40Skip*2ms = 4s
+ kwargs={
+ 'model_path': curr_dir+'/franka/assets/franka_hang_push_v0.xml',
+ 'config_path': curr_dir+'/franka/assets/franka_hang_push_v0.config',
+ 'robot_site_name': "end_effector",
+ 'object_site_name': "obj0",
+ 'obj_pos_limits': {'high':[0.475, 0.025, 1.31], 'low':[0.425, -0.025, 1.3]},
+ 'target_site_name': "target",
+ 'target_xyz_range': {'high':[0.621, 0.0, 1.333], 'low':[0.621, 0.0, 1.333]},
+ 'pos_limits': {'eef_low': [0.3, -0.1, 1.25, 3.14, 0.5, -0.8, 0.2],
+ 'eef_high': [0.8, 0.1, 1.5, 3.14, 0.5, -0.8, 0.2]
+ },
+ 'vel_limits': {'eef':[0.15, 0.15, 0.15],
+ 'jnt': [0.15, 0.25, 0.1, 0.25, 0.1, 0.25, 0.2, 1.0]
+ },
+ 'init_qpos': [0.0227, -0.9291, -0.014, -2.5568, -0.029, 0.5052, -0.783, 0.2, 0.2],
+ }
+)
+
+register(
+ # Init position: [0.36, 0.0, 1.34]
+ # Init euler: [3.14, 0.5, -0.8,]
+ id='FrankaPlanarPush-v0',
+ entry_point='robohive.envs.arms.push_base_v0:PushBaseV0',
+ max_episode_steps=50, #50steps*40Skip*2ms = 4s
+ kwargs={
+ 'model_path': curr_dir+'/franka/assets/franka_planar_push_v0.xml',
+ 'config_path': curr_dir+'/franka/assets/franka_planar_push_v0.config',
+ 'robot_site_name': "end_effector",
+ 'object_site_name': "obj0",
+ 'obj_pos_limits': {'high':[0.52, 0.31, 0.855], 'low':[0.44, 0.25, 0.845]},
+ 'target_site_name': "target",
+ 'target_xyz_range': {'high':[0.48, -0.1, 0.845], 'low':[0.48, -0.1, 0.845]},
+ 'pos_limits': {'eef_low': [0.3, -0.4, 0.865, 3.14, 0.0, 0.28, 0.2],
+ 'eef_high': [0.8, 0.4, 0.965, 3.14, 0.0, 1.28, 0.2]
+ },
+ 'vel_limits': {'eef':[0.15, 0.15, 0.15],
+ 'jnt': [0.15, 0.25, 0.1, 0.25, 0.1, 0.25, 0.2, 1.0]
+ },
+ 'init_qpos': [0.665, 0.567, 0.0, -1.999, 0.0, 0.9172, 1.4541, 0.2, 0.2],
+ }
+)
+
+register(
+ # Init position: [0.36, 0.0, 1.34]
+ # Init euler: [3.14, 0.5, -0.8,]
+ id='FrankaPlanarPushSmall-v0',
+ entry_point='robohive.envs.arms.push_base_v0:PushBaseV0',
+ max_episode_steps=50, #50steps*40Skip*2ms = 4s
+ kwargs={
+ 'model_path': curr_dir+'/franka/assets/franka_planar_push_v0.xml',
+ 'config_path': curr_dir+'/franka/assets/franka_planar_push_v0.config',
+ 'robot_site_name': "end_effector",
+ 'object_site_name': "obj0",
+ 'obj_pos_limits': {'high':[0.52, 0.31, 0.855], 'low':[0.44, 0.25, 0.845]},
+ 'target_site_name': "target",
+ 'target_xyz_range': {'high':[0.48, -0.1, 0.845], 'low':[0.48, -0.1, 0.845]},
+ 'pos_limits': {'eef_low': [0.3, -0.4, 0.865, 3.14, 0.0, 0.28, 0.2],
+ 'eef_high': [0.8, 0.4, 0.965, 3.14, 0.0, 1.28, 0.2]
+ },
+ 'vel_limits': {'eef':[0.15, 0.15, 0.15],
+ 'jnt': [0.15, 0.25, 0.1, 0.25, 0.1, 0.25, 0.2, 1.0]
+ },
+ 'init_qpos': [0.665, 0.567, 0.0, -1.999, 0.0, 0.9172, 1.4541, 0.2, 0.2],
+ }
+)
+
+register(
+ # Init position: [0.36, 0.0, 1.34]
+ # Init euler: [3.14, 0.5, -0.8,]
+ id='FrankaPlanarPushTeleop-v0',
+ entry_point='robohive.envs.arms.push_base_v0:PushBaseV0',
+ max_episode_steps=100, #50steps*40Skip*2ms = 4s
+ kwargs={
+ 'model_path': curr_dir+'/franka/assets/franka_planar_push_teleop_v0.xml',
+ #'config_path': curr_dir+'/franka/assets/franka_planar_push_v0.config',
+ 'config_path': curr_dir+'/franka/assets/franka_planar_push_rp03_v0.config',
+ 'robot_site_name': "end_effector",
+ 'object_site_name': "obj0",
+ 'obj_pos_limits': {'high':[0.52, -0.31, 0.855], 'low':[0.44, -0.25, 0.845]},
+ 'target_site_name': "target",
+ 'target_xyz_range': {'high':[0.48, -0.1, 0.845], 'low':[0.48, -0.1, 0.845]},
+ 'pos_limits': {'eef_low': [0.2, -0.2, 0.9, 3.14, 0.0, 0.28, 0.0],
+ 'eef_high': [0.7, 0.5, 0.95, 3.14, 0.0, 1.28, 0.0]
+ },
+ 'vel_limits': {'eef':[0.15, 0.15, 0.15],
+ 'jnt': [0.15, 0.25, 0.1, 0.25, 0.1, 0.25, 0.2, 1.0]
+ },
+ 'init_qpos': [0.467,0.309,0.088,-2.344,-0.145,1.054,1.4,0.0,0.0],
+ }
+)
+
+register(
+ # Init position: [0.36, 0.0, 1.34]
+ # Init euler: [3.14, 0.5, -0.8,]
+ id='FrankaPlanarPushReal-v0',
+ entry_point='robohive.envs.arms.push_base_v0:PushBaseV0',
+ max_episode_steps=100, #50steps*40Skip*2ms = 4s
+ kwargs={
+ 'model_path': curr_dir+'/franka/assets/franka_planar_push_v0.xml',
+ #'config_path': curr_dir+'/franka/assets/franka_planar_push_v0.config',
+ 'config_path': curr_dir+'/franka/assets/franka_planar_push_rp03_v0.config',
+ 'robot_site_name': "end_effector",
+ 'object_site_name': "obj0",
+ 'obj_pos_limits': {'high':[0.52, 0.31, 0.855], 'low':[0.44, 0.25, 0.845]},
+ 'target_site_name': "target",
+ 'target_xyz_range': {'high':[0.48, -0.1, 0.845], 'low':[0.48, -0.1, 0.845]},
+ 'pos_limits': {'eef_low': [0.2, -0.2, 0.9, 3.14, 0.0, 0.28, 0.0],
+ 'eef_high': [0.7, 0.5, 0.95, 3.14, 0.0, 1.28, 0.0]
+ },
+ 'vel_limits': {'eef':[0.15, 0.15, 0.15],
+ 'jnt': [0.15, 0.25, 0.1, 0.25, 0.1, 0.25, 0.2, 1.0]
+ },
+ 'init_qpos': [0.467,0.309,0.088,-2.344,-0.145,1.054,1.4,0.0,0.0],
+ }
+)
+
+# Reach to random target using visual inputs
+def register_push_visual_envs(env_name, encoder_type, cams, real=False, real_cams=None, small=False):
+ proprio_keys = ['qp', 'qv', 'grasp_pos', 'grasp_rot']
+ visual_keys = []
+ assert((not real and real_cams is None) or (real and real_cams is not None))
+ if not real:
+ if small:
+ for cam in cams:
+ visual_keys.append('rgb:'+cam+':100x100:{}'.format(encoder_type))
+ visual_keys.append('d:'+cam+':100x100:{}'.format(encoder_type))
+ else:
+ for cam in cams:
+ visual_keys.append('rgb:'+cam+':224x224:{}'.format(encoder_type))
+ visual_keys.append('d:'+cam+':224x224:{}'.format(encoder_type))
+ else:
+ for cam in cams:
+ visual_keys.append('rgb:'+cam+':240x424:{}'.format(encoder_type))
+ visual_keys.append('d:'+cam+':240x424:{}'.format(encoder_type))
+ for cam in real_cams:
+ visual_keys.append('rgb:'+cam+':240x424:{}'.format(encoder_type))
+ visual_keys.append('d:'+cam+':240x424:{}'.format(encoder_type))
+
+ register_env_variant(
+ env_id='{}-v0'.format(env_name),
+ variant_id='{}_v{}-v0'.format(env_name, encoder_type),
+ variants={'proprio_keys': proprio_keys,
+ 'visual_keys': visual_keys
+ },
+ silent=True
+ )
+
+push_cams = ['top_cam', 'Franka_wrist_cam']
+real_cams = ['left_cam', 'right_cam']
+for enc in ["r3m18", "r3m34", "r3m50", "1d", "2d"]:
+ register_push_visual_envs('FrankaBinPush', enc, cams=push_cams)
+ register_push_visual_envs('FrankaBinPushSmall', enc, cams=push_cams, small=True)
+ register_push_visual_envs('FrankaBinPushTeleop', enc, cams=push_cams, real_cams=real_cams, real=True)
+ register_push_visual_envs('FrankaBinPushReal', enc, cams=push_cams, real_cams=real_cams, real=True)
+
+for enc in ["r3m18", "r3m34", "r3m50", "1d", "2d"]:
+ register_push_visual_envs('FrankaHangPush', enc, cams=push_cams)
+
+planar_push_cams = ['right_cam', 'Franka_wrist_cam']
+planar_push_real_cams = ['top_cam', 'left_cam']
+for enc in ["r3m18", "r3m34", "r3m50", "1d", "2d"]:
+ register_push_visual_envs('FrankaPlanarPush', enc, cams=planar_push_cams)
+ register_push_visual_envs('FrankaPlanarPushSmall', enc, cams=planar_push_cams, small=True)
+ register_push_visual_envs('FrankaPlanarPushTeleop', enc, cams=planar_push_cams, real_cams=planar_push_real_cams, real=True)
+ register_push_visual_envs('FrankaPlanarPushReal', enc, cams=planar_push_cams, real_cams=planar_push_real_cams, real=True)
+
# FRANKA PICK =======================================================================
register(
id='FrankaPickPlaceFixed-v0',
@@ -125,6 +389,335 @@ def register_visual_envs(encoder_type):
}
)
+register(
+ id='FrankaBinPick-v0',
+ entry_point='robohive.envs.arms.bin_pick_v0:BinPickV0',
+ max_episode_steps=100, #50steps*40Skip*2ms = 4s
+ kwargs={
+ 'model_path': curr_dir+'/franka/assets/franka_bin_pick_v0.xml',
+ 'config_path': curr_dir+'/franka/assets/franka_bin_pick_v0.config',
+ 'robot_site_name': "end_effector",
+ 'object_site_name': "obj0",
+ 'target_site_name': "drop_target",
+ 'randomize': True,
+ 'target_xyz_range': {'high':[0.5, 0.0, 1.1], 'low':[0.5, 0.0, 1.1]}
+ }
+
+)
+
+register(
+ id='FrankaBinPickSmall-v0',
+ entry_point='robohive.envs.arms.bin_pick_v0:BinPickV0',
+ max_episode_steps=100, #50steps*40Skip*2ms = 4s
+ kwargs={
+ 'model_path': curr_dir+'/franka/assets/franka_bin_pick_v0.xml',
+ 'config_path': curr_dir+'/franka/assets/franka_bin_pick_v0.config',
+ 'robot_site_name': "end_effector",
+ 'object_site_name': "obj0",
+ 'target_site_name': "drop_target",
+ 'randomize': True,
+ 'target_xyz_range': {'high':[0.5, 0.0, 1.1], 'low':[0.5, 0.0, 1.1]}
+ }
+
+)
+
+register(
+ id='FrankaBinPickReal-v0',
+ entry_point='robohive.envs.arms.bin_pick_v0:BinPickV0',
+ max_episode_steps=100, #50steps*40Skip*2ms = 4s
+ kwargs={
+ 'model_path': curr_dir+'/franka/assets/franka_bin_pick_v0.xml',
+ 'config_path': curr_dir+'/franka/assets/franka_bin_pick_v0.config',
+ 'robot_site_name': "end_effector",
+ 'object_site_name': "obj0",
+ 'target_site_name': "drop_target",
+ 'randomize': True,
+ 'target_xyz_range': {'high':[0.5, 0.0, 1.1], 'low':[0.5, 0.0, 1.1]},
+ 'init_qpos': [0., 0., 0., -1.7359, 0., 0.2277, -1.57, 0.0]
+ }
+)
+
+register(
+ id='FrankaBinPickRealRP03-v0',
+ entry_point='robohive.envs.arms.bin_pick_v0:BinPickV0',
+ max_episode_steps=100, #50steps*40Skip*2ms = 4s
+ kwargs={
+ 'model_path': curr_dir+'/franka/assets/franka_bin_pick_v0.xml',
+ 'config_path': curr_dir+'/franka/assets/franka_bin_pick_rp03_v0.config',
+ 'robot_site_name': "end_effector",
+ 'object_site_name': "obj0",
+ 'target_site_name': "drop_target",
+ 'randomize': True,
+ 'target_xyz_range': {'high':[0.5, 0.0, 1.1], 'low':[0.5, 0.0, 1.1]},
+ 'init_qpos': [0., 0., 0., -1.7359, 0., 0.2277, -1.57, 0.0]
+ }
+)
+
+register(
+ id='FrankaBinPickRealRP05-v0',
+ entry_point='robohive.envs.arms.bin_pick_v0:BinPickV0',
+ max_episode_steps=100, #50steps*40Skip*2ms = 4s
+ kwargs={
+ 'model_path': curr_dir+'/franka/assets/franka_bin_pick_v0.xml',
+ 'config_path': curr_dir+'/franka/assets/franka_bin_pick_rp05_v0.config',
+ 'robot_site_name': "end_effector",
+ 'object_site_name': "obj0",
+ 'target_site_name': "drop_target",
+ 'randomize': True,
+ 'target_xyz_range': {'high':[0.5, 0.0, 1.1], 'low':[0.5, 0.0, 1.1]},
+ 'init_qpos': [0., 0., 0., -1.7359, 0., 0.2277, -1.57, 0.0]
+ }
+)
+
+# Reach to random target using visual inputs
+def register_bin_pick_visual_envs(env_name, encoder_type, real=False, small=False):
+ proprio_keys = ['qp', 'qv', 'grasp_pos', 'grasp_rot']
+
+ if not real:
+ if small:
+ visual_keys = ["rgb:left_cam:100x100:{}".format(encoder_type),
+ "d:left_cam:100x100:{}".format(encoder_type),
+ "rgb:right_cam:100x100:{}".format(encoder_type),
+ "d:right_cam:100x100:{}".format(encoder_type)]
+ else:
+ visual_keys = ["rgb:left_cam:224x224:{}".format(encoder_type),
+ "d:left_cam:224x224:{}".format(encoder_type),
+ "rgb:right_cam:224x224:{}".format(encoder_type),
+ "d:right_cam:224x224:{}".format(encoder_type)]
+ else:
+ visual_keys = ["rgb:left_cam:240x424:{}".format(encoder_type),
+ "d:left_cam:240x424:{}".format(encoder_type),
+ "rgb:right_cam:240x424:{}".format(encoder_type),
+ "d:right_cam:240x424:{}".format(encoder_type),
+ "rgb:top_cam:240x424:{}".format(encoder_type),
+ "d:top_cam:240x424:{}".format(encoder_type),
+ "rgb:Franka_wrist_cam:240x424:{}".format(encoder_type),
+ "d:Franka_wrist_cam:240x424:{}".format(encoder_type)]
+
+ register_env_variant(
+ env_id='{}-v0'.format(env_name),
+ variant_id='{}_v{}-v0'.format(env_name, encoder_type),
+ variants={'proprio_keys': proprio_keys,
+ 'visual_keys':visual_keys
+ },
+ silent=True
+ )
+for enc in ["r3m18", "r3m34", "r3m50", "1d", "2d"]:
+ register_bin_pick_visual_envs('FrankaBinPick', enc)
+ register_bin_pick_visual_envs('FrankaBinPickSmall', enc, small=True)
+for enc in ["r3m18", "r3m34", "r3m50", "1d", "2d"]:
+ register_bin_pick_visual_envs('FrankaBinPickReal', enc, real=True)
+ register_bin_pick_visual_envs('FrankaBinPickRealRP03', enc, real=True)
+ register_bin_pick_visual_envs('FrankaBinPickRealRP05', enc, real=True)
+
+# REORIENT ====================================================================
+
+register(
+ id='FrankaBinReorient-v0',
+ entry_point='robohive.envs.arms.bin_reorient_v0:BinReorientV0',
+ max_episode_steps=150, #50steps*40Skip*2ms = 4s
+ kwargs={
+ 'model_path': curr_dir+'/franka/assets/franka_dmanus_reorient_v0.xml',
+ 'config_path': curr_dir+'/franka/assets/franka_dmanus_reorient_sim_v0.config',
+ 'robot_site_name': "end_effector",
+ 'object_site_name': "obj0",
+ 'target_site_name': "drop_target",
+ 'hand_site_name': 'palm_site',
+ 'randomize': True,
+ 'target_xyz_range': {'high':[0.5, 0.0, 1.1], 'low':[0.5, 0.0, 1.1]},
+ 'vel_limits': {'jnt': [0.15, 0.25, 0.1, 0.25, 0.1, 0.1, 0.6],
+ 'jnt_slow': [0.1, 0.25, 0.1, 0.25, 0.1, 0.1, 0.6],
+ 'eef': [0.075, 0.075, 0.15, 0.3, 0.3, 0.5],
+ 'eef_slow': [0.075, 0.075, 0.075, 0.3, 0.3, 0.5]},
+ 'max_slow_height': 0.95,
+ 'noise_scale': 0.0,
+ 'obs_delay': 0
+ }
+
+)
+
+register(
+ id='FrankaBinReorientSmall-v0',
+ entry_point='robohive.envs.arms.bin_reorient_v0:BinReorientV0',
+ max_episode_steps=150, #50steps*40Skip*2ms = 4s
+ kwargs={
+ 'model_path': curr_dir+'/franka/assets/franka_dmanus_reorient_v0.xml',
+ 'config_path': curr_dir+'/franka/assets/franka_dmanus_reorient_sim_v0.config',
+ 'robot_site_name': "end_effector",
+ 'object_site_name': "obj0",
+ 'target_site_name': "drop_target",
+ 'hand_site_name': 'palm_site',
+ 'randomize': True,
+ 'target_xyz_range': {'high':[0.5, 0.0, 1.1], 'low':[0.5, 0.0, 1.1]},
+ 'vel_limits': {'jnt': [0.15, 0.25, 0.1, 0.25, 0.1, 0.1, 0.6],
+ 'jnt_slow': [0.1, 0.25, 0.1, 0.25, 0.1, 0.1, 0.6],
+ 'eef': [0.075, 0.075, 0.15, 0.3, 0.3, 0.5],
+ 'eef_slow': [0.075, 0.075, 0.075, 0.3, 0.3, 0.5]},
+ 'max_slow_height': 0.95,
+ 'noise_scale': 0.0,
+ 'obs_delay': 0
+ }
+
+)
+
+register(
+ id='FrankaBinReorientNoisy50-v0',
+ entry_point='robohive.envs.arms.bin_reorient_v0:BinReorientV0',
+ max_episode_steps=150, #50steps*40Skip*2ms = 4s
+ kwargs={
+ 'model_path': curr_dir+'/franka/assets/franka_dmanus_reorient_v0.xml',
+ 'config_path': curr_dir+'/franka/assets/franka_dmanus_reorient_sim_v0.config',
+ 'robot_site_name': "end_effector",
+ 'object_site_name': "obj0",
+ 'target_site_name': "drop_target",
+ 'hand_site_name': 'palm_site',
+ 'randomize': True,
+ 'target_xyz_range': {'high':[0.5, 0.0, 1.1], 'low':[0.5, 0.0, 1.1]},
+ 'vel_limits': {'jnt': [0.15, 0.25, 0.1, 0.25, 0.1, 0.1, 0.6],
+ 'jnt_slow': [0.1, 0.25, 0.1, 0.25, 0.1, 0.1, 0.6],
+ 'eef': [0.075, 0.075, 0.15, 0.3, 0.3, 0.5],
+ 'eef_slow': [0.075, 0.075, 0.075, 0.3, 0.3, 0.5]},
+ 'max_slow_height': 0.95,
+ 'noise_scale': 0.5,
+ 'obs_delay': 0
+ }
+
+)
+
+register(
+ id='FrankaBinReorientNoisy100-v0',
+ entry_point='robohive.envs.arms.bin_reorient_v0:BinReorientV0',
+ max_episode_steps=150, #50steps*40Skip*2ms = 4s
+ kwargs={
+ 'model_path': curr_dir+'/franka/assets/franka_dmanus_reorient_v0.xml',
+ 'config_path': curr_dir+'/franka/assets/franka_dmanus_reorient_sim_v0.config',
+ 'robot_site_name': "end_effector",
+ 'object_site_name': "obj0",
+ 'target_site_name': "drop_target",
+ 'hand_site_name': 'palm_site',
+ 'randomize': True,
+ 'target_xyz_range': {'high':[0.5, 0.0, 1.1], 'low':[0.5, 0.0, 1.1]},
+ 'vel_limits': {'jnt': [0.15, 0.25, 0.1, 0.25, 0.1, 0.1, 0.6],
+ 'jnt_slow': [0.1, 0.25, 0.1, 0.25, 0.1, 0.1, 0.6],
+ 'eef': [0.075, 0.075, 0.15, 0.3, 0.3, 0.5],
+ 'eef_slow': [0.075, 0.075, 0.075, 0.3, 0.3, 0.5]},
+ 'max_slow_height': 0.95,
+ 'noise_scale': 1.0,
+ 'obs_delay': 0
+ }
+
+)
+
+register(
+ id='FrankaBinReorientDelay1-v0',
+ entry_point='robohive.envs.arms.bin_reorient_v0:BinReorientV0',
+ max_episode_steps=150, #50steps*40Skip*2ms = 4s
+ kwargs={
+ 'model_path': curr_dir+'/franka/assets/franka_dmanus_reorient_v0.xml',
+ 'config_path': curr_dir+'/franka/assets/franka_dmanus_reorient_sim_v0.config',
+ 'robot_site_name': "end_effector",
+ 'object_site_name': "obj0",
+ 'target_site_name': "drop_target",
+ 'hand_site_name': 'palm_site',
+ 'randomize': True,
+ 'target_xyz_range': {'high':[0.5, 0.0, 1.1], 'low':[0.5, 0.0, 1.1]},
+ 'vel_limits': {'jnt': [0.15, 0.25, 0.1, 0.25, 0.1, 0.1, 0.6],
+ 'jnt_slow': [0.1, 0.25, 0.1, 0.25, 0.1, 0.1, 0.6],
+ 'eef': [0.075, 0.075, 0.15, 0.3, 0.3, 0.5],
+ 'eef_slow': [0.075, 0.075, 0.075, 0.3, 0.3, 0.5]},
+ 'max_slow_height': 0.95,
+ 'noise_scale': 0.0,
+ 'obs_delay': 1
+ }
+
+)
+
+register(
+ id='FrankaBinReorientDelay2-v0',
+ entry_point='robohive.envs.arms.bin_reorient_v0:BinReorientV0',
+ max_episode_steps=150, #50steps*40Skip*2ms = 4s
+ kwargs={
+ 'model_path': curr_dir+'/franka/assets/franka_dmanus_reorient_v0.xml',
+ 'config_path': curr_dir+'/franka/assets/franka_dmanus_reorient_sim_v0.config',
+ 'robot_site_name': "end_effector",
+ 'object_site_name': "obj0",
+ 'target_site_name': "drop_target",
+ 'hand_site_name': 'palm_site',
+ 'randomize': True,
+ 'target_xyz_range': {'high':[0.5, 0.0, 1.1], 'low':[0.5, 0.0, 1.1]},
+ 'vel_limits': {'jnt': [0.15, 0.25, 0.1, 0.25, 0.1, 0.1, 0.6],
+ 'jnt_slow': [0.1, 0.25, 0.1, 0.25, 0.1, 0.1, 0.6],
+ 'eef': [0.075, 0.075, 0.15, 0.3, 0.3, 0.5],
+ 'eef_slow': [0.075, 0.075, 0.075, 0.3, 0.3, 0.5]},
+ 'max_slow_height': 0.95,
+ 'noise_scale': 0.0,
+ 'obs_delay': 2
+ }
+
+)
+
+register(
+ id='FrankaBinReorientReal-v0',
+ entry_point='robohive.envs.arms.bin_reorient_v0:BinReorientV0',
+ max_episode_steps=150, #50steps*40Skip*2ms = 4s
+ kwargs={
+ 'model_path': curr_dir+'/franka/assets/franka_dmanus_reorient_v0.xml',
+ 'config_path': curr_dir+'/franka/assets/franka_dmanus_reorient_real_v0.config',
+ 'robot_site_name': "end_effector",
+ 'object_site_name': "obj0",
+ 'target_site_name': "drop_target",
+ 'hand_site_name': 'palm_site',
+ 'randomize': True,
+ 'target_xyz_range': {'high':[0.5, 0.0, 1.1], 'low':[0.5, 0.0, 1.1]},
+ 'vel_limits': {'jnt': [0.15, 0.25, 0.1, 0.25, 0.1, 0.1, 0.3],
+ 'jnt_slow': [0.1, 0.25, 0.1, 0.25, 0.1, 0.1, 0.3],
+ 'eef': [0.075, 0.075, 0.15, 0.3, 0.3, 0.5],
+ 'eef_slow': [0.075, 0.075, 0.1, 0.3, 0.3, 0.5]},
+ 'max_slow_height':1.075
+ }
+
+)
+
+# Reach to random target using visual inputs
+def register_bin_reorient_visual_envs(env_name, encoder_type, real=False, small=False):
+ proprio_keys = ['qp', 'qv', 'grasp_pos', 'grasp_rot']
+
+ if not real:
+ if small:
+ visual_keys = ["rgb:left_cam:100x100:{}".format(encoder_type),
+ "d:left_cam:100x100:{}".format(encoder_type),
+ "rgb:right_cam:100x100:{}".format(encoder_type),
+ "d:right_cam:100x100:{}".format(encoder_type)]
+ else:
+ visual_keys = ["rgb:left_cam:224x224:{}".format(encoder_type),
+ "d:left_cam:224x224:{}".format(encoder_type),
+ "rgb:right_cam:224x224:{}".format(encoder_type),
+ "d:right_cam:224x224:{}".format(encoder_type)]
+ else:
+ visual_keys = ["rgb:left_cam:240x424:{}".format(encoder_type),
+ "d:left_cam:240x424:{}".format(encoder_type),
+ "rgb:right_cam:240x424:{}".format(encoder_type),
+ "d:right_cam:240x424:{}".format(encoder_type),
+ "rgb:top_cam:240x424:{}".format(encoder_type),
+ "d:top_cam:240x424:{}".format(encoder_type)]
+
+ register_env_variant(
+ env_id='{}-v0'.format(env_name),
+ variant_id='{}_v{}-v0'.format(env_name, encoder_type),
+ variants={'proprio_keys': proprio_keys,
+ 'visual_keys':visual_keys
+ },
+ silent=True
+ )
+
+for enc in ["r3m18", "r3m34", "r3m50", "1d", "2d"]:
+ register_bin_reorient_visual_envs('FrankaBinReorient', enc)
+ register_bin_reorient_visual_envs('FrankaBinReorientSmall', enc, small=True)
+ register_bin_reorient_visual_envs('FrankaBinReorientNoisy50', enc)
+ register_bin_reorient_visual_envs('FrankaBinReorientNoisy100', enc)
+ register_bin_reorient_visual_envs('FrankaBinReorientDelay1', enc)
+ register_bin_reorient_visual_envs('FrankaBinReorientDelay2', enc)
+ register_bin_reorient_visual_envs('FrankaBinReorientReal', enc, real=True)
# FETCH =======================================================================
from robohive.envs.arms.reach_base_v0 import ReachBaseV0
diff --git a/robohive/envs/arms/bin_pick_v0.py b/robohive/envs/arms/bin_pick_v0.py
new file mode 100644
index 00000000..ef711c31
--- /dev/null
+++ b/robohive/envs/arms/bin_pick_v0.py
@@ -0,0 +1,452 @@
+""" =================================================
+Copyright (C) 2018 Vikash Kumar
+Author :: Vikash Kumar (vikashplus@gmail.com)
+Source :: https://github.com/vikashplus/robohive
+License :: Under Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
+================================================= """
+
+import os
+import sys
+import collections
+import gym
+import numpy as np
+
+from robohive.envs import env_base
+from robohive.physics.sim_scene import SimScene
+from robohive.utils.quat_math import euler2quat, mat2euler, quat2euler, mat2quat
+from robohive.utils.xml_utils import reassign_parent
+from robohive.utils.inverse_kinematics import qpos_from_site_pose
+
+class BinPickV0(env_base.MujocoEnv):
+
+ DEFAULT_OBS_KEYS = [
+ 'qp', 'qv', 'grasp_pos', 'grasp_rot', 'object_err', 'target_err'
+ ]
+ DEFAULT_RWD_KEYS_AND_WEIGHTS = {
+ "object_dist": -1.0,
+ "target_dist": -2.5,
+ "bonus": 10.0,
+ "penalty": -50,
+ }
+
+ def __init__(self, model_path, obsd_model_path=None, seed=None, **kwargs):
+
+
+ # Process model to use Robotiq/DManus as end effector
+ raw_sim = SimScene.get_sim(model_path)
+ raw_xml = raw_sim.model.get_xml()
+ processed_xml = reassign_parent(xml_str=raw_xml, receiver_node="panda0_link7", donor_node="ee_mount")
+ processed_model_path = model_path[:-4]+"_processed.xml"
+
+ cur_xml = None
+ if os.path.exists(processed_model_path):
+ with open(processed_model_path,'r') as file:
+ cur_xml = file.read()
+
+ if cur_xml != processed_xml:
+ with open(processed_model_path, 'w') as file:
+ file.write(processed_xml)
+
+ # Process model to use DManus as end effector
+ if obsd_model_path == model_path:
+ processed_obsd_model_path = processed_model_path
+ elif obsd_model_path:
+ raw_sim = SimScene.get_sim(obsd_model_path)
+ raw_xml = raw_sim.model.get_xml()
+ processed_xml = reassign_parent(xml_str=raw_xml, receiver_node="panda0_link7", donor_node="ee_mount")
+ processed_obsd_model_path = obsd_model_path[:-4]+"_processed.xml"
+
+ cur_xml = None
+ if os.path.exists(processed_obsd_model_path):
+ with open(processed_obsd_model_path,'r') as file:
+ cur_xml = file.read()
+ if cur_xml != processed_xml:
+ with open(processed_obsd_model_path, 'w') as file:
+ file.write(processed_xml)
+ else:
+ processed_obsd_model_path = None
+
+ # EzPickle.__init__(**locals()) is capturing the input dictionary of the init method of this class.
+ # In order to successfully capture all arguments we need to call gym.utils.EzPickle.__init__(**locals())
+ # at the leaf level, when we do inheritance like we do here.
+ # kwargs is needed at the top level to account for injection of __class__ keyword.
+ # Also see: https://github.com/openai/gym/pull/1497
+ gym.utils.EzPickle.__init__(self, model_path, obsd_model_path, seed, **kwargs)
+
+ # This two step construction is required for pickling to work correctly. All arguments to all __init__
+ # calls must be pickle friendly. Things like sim / sim_obsd are NOT pickle friendly. Therefore we
+ # first construct the inheritance chain, which is just __init__ calls all the way down, with env_base
+ # creating the sim / sim_obsd instances. Next we run through "setup" which relies on sim / sim_obsd
+ # created in __init__ to complete the setup.
+ super().__init__(model_path=processed_model_path, obsd_model_path=processed_obsd_model_path, seed=seed)
+
+ self._setup(processed_model_path, **kwargs)
+
+ def _setup(self,
+ model_path,
+ robot_site_name,
+ object_site_name,
+ target_site_name,
+ target_xyz_range,
+ init_qpos = None,
+ frame_skip=40,
+ reward_mode="dense",
+ obs_keys=DEFAULT_OBS_KEYS,
+ weighted_reward_keys=DEFAULT_RWD_KEYS_AND_WEIGHTS,
+ randomize=False,
+ pos_limits = {'eef_low': [0.368, -0.25, 0.9, -np.pi, 0, -np.pi, 0.0],
+ 'eef_high':[0.72, 0.25, 1.3, np.pi, 2*np.pi, 0, 0.835]},
+ vel_limits = {'jnt': [0.15, 0.25, 0.1, 0.25, 0.1, 0.1, 0.35, 0.835],
+ 'jnt_slow': [0.1, 0.25, 0.1, 0.25, 0.1, 0.1, 0.35, 0.835],
+ 'eef': [0.075, 0.075, 0.15, 0.3, 0.3, 0.5, 0.835],
+ 'eef_slow': [0.075, 0.075, 0.075, 0.3, 0.3, 0.5, 0.835]},
+ obj_pos_limits = {'low': [0.4, -0.2, 0.855],
+ 'high': [0.6, 0.2, 0.855]},
+ min_grab_height=0.905,
+ max_slow_height=1.075,
+ max_ik=3,
+ **kwargs,
+ ):
+
+ # ids
+ self.grasp_sid = self.sim.model.site_name2id(robot_site_name)
+ self.object_site_name = object_site_name
+ self.object_sid = self.sim.model.site_name2id(object_site_name)
+ self.target_sid = self.sim.model.site_name2id(target_site_name)
+ self.target_xyz_range = target_xyz_range
+ self.randomize = randomize
+ self.pos_limits = pos_limits
+ self.vel_limits = vel_limits
+ self.obj_pos_limits = obj_pos_limits
+ self.min_grab_height = min_grab_height
+ self.max_slow_height = max_slow_height
+ self.max_ik = max_ik
+ self.last_eef_cmd = None
+
+ self.ik_sim = SimScene.get_sim(model_path)
+ self.pos_limits['jnt_low'] = self.sim.model.jnt_range[:self.sim.model.nu, 0]
+ self.pos_limits['jnt_high'] = self.sim.model.jnt_range[:self.sim.model.nu, 1]
+
+ for key in pos_limits.keys():
+ pos_limits[key] = np.array(pos_limits[key])
+ for key in vel_limits.keys():
+ vel_limits[key] = np.array(vel_limits[key])
+ for key in obj_pos_limits.keys():
+ obj_pos_limits[key] = np.array(obj_pos_limits[key])
+
+ super()._setup(obs_keys=obs_keys,
+ weighted_reward_keys=weighted_reward_keys,
+ reward_mode=reward_mode,
+ frame_skip=frame_skip,
+ **kwargs)
+ if init_qpos is not None:
+ self.init_qpos[:len(init_qpos)] = np.array(init_qpos)[:]
+ self.viewer_setup(distance=1.25, azimuth=-90, elevation=-20)
+
+ if self.pos_limits is not None:
+ act_low = -np.ones(self.pos_limits['eef_low'].shape[0]) if self.normalize_act else self.pos_limits['eef_low'].copy()
+ act_high = np.ones(self.pos_limits['eef_high'].shape[0]) if self.normalize_act else self.pos_limits['eef_high'].copy()
+ self.action_space = gym.spaces.Box(act_low, act_high, dtype=np.float32)
+
+
+ def get_obs_dict(self, sim):
+ obs_dict = {}
+ obs_dict['time'] = np.array([self.sim.data.time])
+ obs_dict['qp'] = sim.data.qpos.copy()
+ obs_dict['qv'] = sim.data.qvel.copy()
+ obs_dict['grasp_pos'] = sim.data.site_xpos[self.grasp_sid].copy()
+ obs_dict['grasp_rot'] = mat2quat(self.sim.data.site_xmat[self.grasp_sid].reshape(3,3).transpose())
+ obs_dict['object_err'] = sim.data.site_xpos[self.object_sid]-sim.data.site_xpos[self.grasp_sid]
+ obs_dict['target_err'] = sim.data.site_xpos[self.target_sid]-sim.data.site_xpos[self.object_sid]
+ return obs_dict
+
+
+ def get_reward_dict(self, obs_dict):
+ object_dist = np.linalg.norm(obs_dict['object_err'], axis=-1)
+ target_dist = np.linalg.norm(obs_dict['target_err'], axis=-1)
+ far_th = 1.25
+
+ rwd_dict = collections.OrderedDict((
+ # Optional Keys
+ ('object_dist', object_dist),
+ ('target_dist', target_dist),
+ ('bonus', (target_dist<.1) + (target_dist<.05)),
+ ('penalty', (object_dist>far_th)),
+ # Must keys
+ ('sparse', target_dist<.075),
+ ('solved', target_dist<.075),
+ ('done', object_dist > far_th),
+ ))
+ rwd_dict['dense'] = np.sum([wt*rwd_dict[key] for key, wt in self.rwd_keys_wt.items()], axis=0)
+ return rwd_dict
+
+ def reset(self, reset_qpos=None, reset_qvel=None, **kwargs):
+
+ if reset_qpos is None:
+ reset_qpos = self.init_qpos.copy()
+
+ if self.randomize:
+ # target location
+ self.sim.model.site_pos[self.target_sid] = self.np_random.uniform(high=self.target_xyz_range['high'], low=self.target_xyz_range['low'])
+
+ # Randomize obj pose
+ obj_jid = self.sim.model.joint_name2id(self.object_site_name)
+ reset_qpos[obj_jid:obj_jid+3] = self.np_random.uniform(low=self.obj_pos_limits['low'],
+ high=self.obj_pos_limits['high'])
+ reset_qpos[obj_jid+3:obj_jid+7] = euler2quat(self.np_random.uniform(low=(0, 0, -np.pi/2), high=(0, 0, np.pi/2)) ) # random quat
+
+ self.sim.forward()
+
+ obs = super().reset(reset_qpos, reset_qvel, blocking=False, **kwargs)
+
+ cur_pos = self.sim.data.site_xpos[self.grasp_sid]
+ cur_rot = mat2euler(self.sim.data.site_xmat[self.grasp_sid].reshape(3,3).transpose())
+ cur_rot[np.abs(cur_rot-np.array([np.pi,0.0,0.0]))>np.abs(cur_rot+2*np.pi-np.array([np.pi,0.0,0.0]))] += 2*np.pi
+ cur_rot[np.abs(cur_rot-np.array([np.pi,0.0,0.0]))>np.abs(cur_rot-2*np.pi-np.array([np.pi,0.0,0.0]))] -= 2*np.pi
+ self.last_eef_cmd = np.concatenate([cur_pos,
+ cur_rot,
+ [self.sim.data.qpos[7]]])
+
+ return obs
+
+ def get_ik_action(self, eef_pos, eef_quat):
+ for i in range(self.max_ik):
+
+ self.ik_sim.data.qpos[:7] = np.random.normal(self.sim.data.qpos[:7], i*0.1)
+
+ self.ik_sim.data.qpos[2] = 0.0
+ self.ik_sim.data.qpos[3] = -2.0
+ self.ik_sim.forward()
+
+ ik_result = qpos_from_site_pose(physics = self.ik_sim,
+ site_name = self.sim.model.site_id2name(self.grasp_sid),
+ target_pos= eef_pos,
+ target_quat= eef_quat,
+ inplace=False,
+ regularization_strength=1.0)
+
+ if ik_result.success:
+ break
+ return ik_result
+
+ def step(self, a, **kwargs):
+ assert(len(a.shape) == 1)
+ assert(a.shape[0] == self.sim.model.nu or a.shape[0] == 7)
+
+ jnt_act_low = self.sim.model.actuator_ctrlrange[:,0].copy()
+ jnt_act_high = self.sim.model.actuator_ctrlrange[:,1].copy()
+ cur_pose = None
+
+ if a.shape[0] == self.sim.model.nu:
+ action = a
+
+ if self.normalize_act:
+ action = (0.5*action+0.5)*(jnt_act_high-jnt_act_low)+jnt_act_low
+
+ else:
+ # Un-normalize cmd
+ eef_cmd = a
+ if self.normalize_act:
+ eef_cmd = (0.5*eef_cmd+0.5)*(self.pos_limits['eef_high']-self.pos_limits['eef_low'])+self.pos_limits['eef_low']
+ eef_cmd = np.clip(eef_cmd,
+ self.pos_limits['eef_low'],
+ self.pos_limits['eef_high'])
+
+ # Get current position and rotation of eef
+ cur_rot = mat2euler(self.sim.data.site_xmat[self.grasp_sid].reshape(3,3).transpose())
+ cur_rot[np.abs(cur_rot-eef_cmd[3:6])>np.abs(cur_rot+2*np.pi-eef_cmd[3:6])] += 2*np.pi
+ cur_rot[np.abs(cur_rot-eef_cmd[3:6])>np.abs(cur_rot-2*np.pi-eef_cmd[3:6])] -= 2*np.pi
+ cur_pose = np.concatenate([self.sim.data.site_xpos[self.grasp_sid],
+ cur_rot,
+ [self.sim.data.qpos[7]]])
+
+ # Enforce cartesian velocity limits
+ if cur_pose[2] < self.max_slow_height:# and self.robot.is_hardware:
+ eef_cmd = np.clip(eef_cmd,
+ cur_pose-self.vel_limits['eef_slow'],
+ cur_pose+self.vel_limits['eef_slow'])
+ else:
+ eef_cmd = np.clip(eef_cmd,
+ cur_pose-self.vel_limits['eef'],
+ cur_pose+self.vel_limits['eef'])
+
+ # Exponential moving average to limit jerk
+ assert self.last_eef_cmd is not None
+ eef_cmd[:6] = 0.25*eef_cmd[:6] + 0.75*self.last_eef_cmd[:6]
+
+ # Prepare for IK, execute last successful command if IK fails
+ eef_pos = eef_cmd[:3]
+ eef_elr = eef_cmd[3:6]
+ eef_quat= euler2quat(eef_elr)
+
+ ik_result = self.get_ik_action(eef_pos, eef_quat)
+ ik_success = ik_result.success
+ if not ik_success:
+ eef_cmd = self.last_eef_cmd
+ eef_pos = eef_cmd[:3]
+ eef_elr = eef_cmd[3:6]
+ eef_quat = euler2quat(eef_elr)
+ ik_result = self.get_ik_action(eef_pos, eef_quat)
+
+ action = ik_result.qpos[:self.sim.model.nu]
+
+ # Check that we are not initiating a grasp at too low of height
+ if ((eef_cmd[6] > sys.float_info.epsilon) and
+ self.sim.data.site_xpos[self.grasp_sid][2] < self.min_grab_height and self.robot.is_hardware):
+ print('Cant grasp this low, z = {}'.format(self.sim.data.site_xpos[self.grasp_sid][2]))
+ action[7:self.sim.model.nu] = 0.0
+ else:
+ action[7:self.sim.model.nu] = eef_cmd[6]
+
+ self.last_eef_cmd = eef_cmd
+
+ # Enforce joint position limits
+ action = np.clip(action, jnt_act_low, jnt_act_high)
+
+ # Enforce joint velocity limits
+ if cur_pose is not None and cur_pose[2] < self.max_slow_height:
+ action = np.clip(action,
+ self.sim.data.qpos[:self.sim.model.nu]-self.vel_limits['jnt_slow'],
+ self.sim.data.qpos[:self.sim.model.nu]+self.vel_limits['jnt_slow'])
+ else:
+ action = np.clip(action,
+ self.sim.data.qpos[:self.sim.model.nu]-self.vel_limits['jnt'],
+ self.sim.data.qpos[:self.sim.model.nu]+self.vel_limits['jnt'])
+
+ if self.normalize_act:
+ action = 2*(((action - jnt_act_low)/(jnt_act_high-jnt_act_low))-0.5)
+
+ self.last_ctrl = self.robot.step(ctrl_desired=action,
+ ctrl_normalized=self.normalize_act,
+ step_duration=self.dt,
+ realTimeSim=self.mujoco_render_frames,
+ render_cbk=self.mj_render if self.mujoco_render_frames else None)
+ return self.forward(**kwargs)
+
+class BinPickPolicy():
+ def __init__(self,
+ env,
+ seed,
+ begin_descent_thresh=0.05,
+ begin_grasp_thresh=0.08,
+ align_height=1.075,
+ is_reset_policy=False):
+
+ self.env = env
+ self.seed = seed
+ self.yaw = np.random.uniform(low=self.env.pos_limits['jnt_low'][6],
+ high=self.env.pos_limits['jnt_high'][6])
+ self.last_t = 0.0
+ self.stage = 0
+ self.is_reset_policy = is_reset_policy
+ self.last_qp = None
+ if env.robot.is_hardware and self.is_reset_policy:
+ self.move_thresh = 0.01
+ else:
+ self.move_thresh = 0.03
+
+ self.begin_descent_thresh = begin_descent_thresh
+ self.begin_grasp_thresh = begin_grasp_thresh
+ self.align_height = align_height
+ self.gripper_close_thresh = 1e-8 if (self.env.robot.is_hardware and self.is_reset_policy) else 0.001
+ self.real_obj_pos = None
+ self.real_tar_pos = None
+
+ def is_moving(self, qp):
+ assert(self.last_qp is not None and qp is not None)
+ return np.linalg.norm(qp - self.last_qp) > self.move_thresh
+
+ def set_real_obj_pos(self, real_obj_pos):
+ self.real_obj_pos = real_obj_pos
+
+ def set_real_tar_pos(self, real_tar_pos):
+ self.real_tar_pos = real_tar_pos
+
+ def set_real_yaw(self, real_yaw):
+ self.yaw = real_yaw
+
+ def get_action(self, obs):
+ obs_dict = self.env.obsvec2obsdict(np.expand_dims(obs, axis=(0,1)))
+
+ if not self.env.robot.is_hardware:
+ self.yaw = -np.pi/4-quat2euler(obs_dict['qp'][0,0,-4:])[-1]
+ while self.yaw < self.env.pos_limits['eef_low'][5]:
+ self.yaw += 2*np.pi
+ while self.yaw > self.env.pos_limits['eef_high'][5]:
+ self.yaw -= 2*np.pi
+
+ action = np.concatenate([obs_dict['grasp_pos'][0, 0, :], [np.pi, 0.0, self.yaw], [obs_dict['qp'][0, 0, 7]]])
+
+ if self.env.robot.is_hardware and self.real_obj_pos is not None:
+ obj_err = self.real_obj_pos-obs_dict['grasp_pos'][0, 0, :]
+ else:
+ obj_err = obs_dict['object_err'][0,0,:]
+ obj_err[2] = obj_err[2] - 0.015
+
+ if self.env.robot.is_hardware and self.real_tar_pos is not None:
+ tar_err = self.real_tar_pos-obs_dict['grasp_pos'][0, 0, :]
+ else:
+ tar_err = obs_dict['target_err'][0,0,:]
+
+ if self.last_t > self.env.sim.data.time:
+ # Reset
+ self.stage = 0
+ self.last_qp = None
+ elif self.stage == 0: # Wait until aligned xy
+ # Advance to next stage?
+ if (np.linalg.norm(obj_err[:2]) < self.begin_descent_thresh and
+ (self.last_qp is not None and not self.is_moving(obs_dict['qp'][0,0,:]))):
+ self.stage = 1
+ elif self.stage == 1:# Wait until close pregrasp
+ if (np.linalg.norm(obj_err[:2]) < self.begin_grasp_thresh or
+ (self.last_qp is not None and not self.is_moving(obs_dict['qp'][0,0,:]))):
+ self.stage = 2
+ elif self.stage == 2: # Wait until pregrasp has stabilized
+ # Advance to next stage?
+ if self.last_qp is not None and not self.is_moving(obs_dict['qp'][0,0,:]):
+ self.stage = 3
+ elif self.stage == 3: # Wait for gripper to start closing
+ # Advance to next stage?
+ if self.last_qp is not None and obs_dict['qp'][0,0,7] > self.last_qp[7]:
+ self.stage = 4
+ elif self.stage == 4: # Wait for gripper to stop closing
+ if self.last_qp is not None and np.abs(self.last_qp[7] - obs_dict['qp'][0,0,7]) < self.gripper_close_thresh:
+ self.stage = 5
+
+ self.last_t = self.env.sim.data.time
+ self.last_qp = obs_dict['qp'][0,0,:]
+
+ #print('Stage {}, t {}'.format(self.stage, self.last_t))
+ if self.stage == 0: # Align in xy
+ action[2] = self.align_height
+ action[:2] += 1.5*obj_err[0:2]
+ action[6] = 0.0
+ elif self.stage == 1 or self.stage == 2: # Move to pregrasp
+ action[:2] += 1.5*obj_err[0:2]
+ action[2] += obj_err[2]
+ action[6] = 0.0
+ elif self.stage == 3 or self.stage == 4: # Close gripper
+ action[:3] += obj_err[0:3]
+ action[6] = 0.835
+ elif self.stage == 5: # Move to target pose
+ action[:3] += tar_err[0:3]
+ action[6] = 0.835
+
+ if self.stage >= 1 and not self.env.robot.is_hardware:
+ action[2] += 0.08
+
+ action = np.clip(action, self.env.pos_limits['eef_low'], self.env.pos_limits['eef_high'])
+
+ cur_rot = mat2euler(self.env.sim.data.site_xmat[self.env.grasp_sid].reshape(3,3).transpose())
+ cur_rot[np.abs(cur_rot-action[3:6])>np.abs(cur_rot+2*np.pi-action[3:6])] += 2*np.pi
+ cur_rot[np.abs(cur_rot-action[3:6])>np.abs(cur_rot-2*np.pi-action[3:6])] -= 2*np.pi
+ cur_pos = np.concatenate([self.env.sim.data.site_xpos[self.env.grasp_sid],
+ cur_rot,
+ [self.env.sim.data.qpos[7]]])
+ action = np.clip(action, cur_pos-self.env.vel_limits['eef'], cur_pos+self.env.vel_limits['eef'])
+
+ # Normalize action to be between -1 and 1
+ action = 2*(((action - self.env.pos_limits['eef_low']) / (np.abs(self.env.pos_limits['eef_high'] - self.env.pos_limits['eef_low'])+1e-8)) - 0.5)
+ action = np.clip(action, -1, 1)
+ noise_action = np.clip(action + 0.1 * np.random.randn(action.shape[0]), -1, 1)
+ return noise_action, {'evaluation': action}
\ No newline at end of file
diff --git a/robohive/envs/arms/bin_reorient_v0.py b/robohive/envs/arms/bin_reorient_v0.py
new file mode 100644
index 00000000..f24e6a83
--- /dev/null
+++ b/robohive/envs/arms/bin_reorient_v0.py
@@ -0,0 +1,689 @@
+""" =================================================
+Copyright (C) 2018 Vikash Kumar
+Author :: Vikash Kumar (vikashplus@gmail.com)
+Source :: https://github.com/vikashplus/robohive
+License :: Under Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
+================================================= """
+
+import os
+import sys
+import collections
+import gym
+import numpy as np
+
+from robohive.envs import env_base
+from robohive.physics.sim_scene import SimScene
+from robohive.utils.quat_math import euler2quat, mat2euler, quat2euler, mat2quat, quat2mat
+from robohive.utils.xml_utils import reassign_parent
+from robohive.utils.inverse_kinematics import qpos_from_site_pose
+
+class BinReorientV0(env_base.MujocoEnv):
+
+ DEFAULT_OBS_KEYS = [
+ 'qp', 'qv', 'grasp_pos', 'grasp_rot', 'object_err', 'target_err'
+ ]
+ DEFAULT_RWD_KEYS_AND_WEIGHTS = {
+ "object_dist": -0.0,
+ "target_dist": -1.0,
+ "bonus": 10.0,
+ "penalty": -50,
+ }
+
+ def __init__(self, model_path, obsd_model_path=None, seed=None, **kwargs):
+
+
+ # Process model to use Robotiq/DManus as end effector
+ raw_sim = SimScene.get_sim(model_path)
+ raw_xml = raw_sim.model.get_xml()
+ processed_xml = reassign_parent(xml_str=raw_xml, receiver_node="panda0_link7", donor_node="ee_mount")
+ processed_model_path = model_path[:-4]+"_processed.xml"
+
+ cur_xml = None
+ if os.path.exists(processed_model_path):
+ with open(processed_model_path,'r') as file:
+ cur_xml = file.read()
+
+ if cur_xml != processed_xml:
+ with open(processed_model_path, 'w') as file:
+ file.write(processed_xml)
+
+ # Process model to use DManus as end effector
+ if obsd_model_path == model_path:
+ processed_obsd_model_path = processed_model_path
+ elif obsd_model_path:
+ raw_sim = SimScene.get_sim(obsd_model_path)
+ raw_xml = raw_sim.model.get_xml()
+ processed_xml = reassign_parent(xml_str=raw_xml, receiver_node="panda0_link7", donor_node="ee_mount")
+ processed_obsd_model_path = obsd_model_path[:-4]+"_processed.xml"
+
+ cur_xml = None
+ if os.path.exists(processed_obsd_model_path):
+ with open(processed_obsd_model_path,'r') as file:
+ cur_xml = file.read()
+ if cur_xml != processed_xml:
+ with open(processed_obsd_model_path, 'w') as file:
+ file.write(processed_xml)
+ else:
+ processed_obsd_model_path = None
+
+ # EzPickle.__init__(**locals()) is capturing the input dictionary of the init method of this class.
+ # In order to successfully capture all arguments we need to call gym.utils.EzPickle.__init__(**locals())
+ # at the leaf level, when we do inheritance like we do here.
+ # kwargs is needed at the top level to account for injection of __class__ keyword.
+ # Also see: https://github.com/openai/gym/pull/1497
+ gym.utils.EzPickle.__init__(self, model_path, obsd_model_path, seed, **kwargs)
+
+ # This two step construction is required for pickling to work correctly. All arguments to all __init__
+ # calls must be pickle friendly. Things like sim / sim_obsd are NOT pickle friendly. Therefore we
+ # first construct the inheritance chain, which is just __init__ calls all the way down, with env_base
+ # creating the sim / sim_obsd instances. Next we run through "setup" which relies on sim / sim_obsd
+ # created in __init__ to complete the setup.
+ super().__init__(model_path=processed_model_path, obsd_model_path=processed_obsd_model_path, seed=seed)
+
+ self._setup(processed_model_path, **kwargs)
+
+ def _setup(self,
+ model_path,
+ robot_site_name,
+ object_site_name,
+ target_site_name,
+ target_xyz_range,
+ hand_site_name,
+ init_qpos = None,
+ frame_skip=40,
+ reward_mode="dense",
+ obs_keys=DEFAULT_OBS_KEYS,
+ weighted_reward_keys=DEFAULT_RWD_KEYS_AND_WEIGHTS,
+ randomize=False,
+ geom_sizes={'high': [0.0585,0.0525], 'low': [0.0585,0.0475]},
+ pos_limits = {'eef_low': [0.368, -0.25, 0.86, -np.pi, 0, -np.pi],
+ 'eef_high':[0.72, 0.25, 1.3, np.pi, 2*np.pi, np.pi]},
+ vel_limits = {'jnt': [0.15, 0.25, 0.1, 0.25, 0.1, 0.1, 0.6], #SET in INIT
+ 'jnt_slow': [0.1, 0.25, 0.1, 0.25, 0.1, 0.1, 0.6],
+ 'eef': [0.075, 0.075, 0.15, 0.3, 0.3, 0.5],
+ 'eef_slow': [0.075, 0.075, 0.1, 0.3, 0.3, 0.5]},
+ obj_pos_limits = {'low': [0.475, -0.025, 0.875],
+ 'high': [0.525, 0.025, 0.875]},
+ min_grab_height=0.905,
+ max_slow_height=1.075, # SET in INIT
+ max_ik=3,
+ **kwargs,
+ ):
+
+ # ids
+ self.grasp_sid = self.sim.model.site_name2id(robot_site_name)
+ self.object_site_name = object_site_name
+ self.object_sid = self.sim.model.site_name2id(object_site_name)
+ self.target_sid = self.sim.model.site_name2id(target_site_name)
+ self.target_xyz_range = target_xyz_range
+ self.hand_sid = self.sim.model.site_name2id(hand_site_name)
+ self.randomize = randomize
+ self.geom_sizes = geom_sizes
+ self.pos_limits = pos_limits
+ self.vel_limits = vel_limits
+ self.obj_pos_limits = obj_pos_limits
+ self.min_grab_height = min_grab_height
+ self.max_slow_height = max_slow_height
+ self.max_ik = max_ik
+ self.last_eef_cmd = None
+ self.random_size = 0.05
+ self.ik_sim = SimScene.get_sim(model_path)
+ self.pos_limits['jnt_low'] = self.sim.model.jnt_range[:self.sim.model.nu, 0]
+ self.pos_limits['jnt_high'] = self.sim.model.jnt_range[:self.sim.model.nu, 1]
+
+ for key in pos_limits.keys():
+ pos_limits[key] = np.array(pos_limits[key])
+ for key in vel_limits.keys():
+ vel_limits[key] = np.array(vel_limits[key])
+ for key in obj_pos_limits.keys():
+ obj_pos_limits[key] = np.array(obj_pos_limits[key])
+
+ assert(pos_limits['eef_low'].shape == pos_limits['eef_high'].shape)
+ if pos_limits['eef_low'].shape[0] == 6:
+ pos_limits['eef_low'] = np.concatenate([pos_limits['eef_low'], self.sim.model.jnt_range[:self.sim.model.nu, 0][7:]])
+ pos_limits['eef_high'] = np.concatenate([pos_limits['eef_high'], self.sim.model.jnt_range[:self.sim.model.nu, 1][7:]])
+
+ assert(vel_limits['jnt'].shape == vel_limits['jnt_slow'].shape)
+ if vel_limits['jnt'].shape[0] == 7:
+ vel_limits['jnt'] = np.concatenate([vel_limits['jnt'], 5*np.ones(10)])
+ vel_limits['jnt_slow'] = np.concatenate([vel_limits['jnt_slow'], 5*np.ones(10)])
+
+ assert(vel_limits['eef'].shape == vel_limits['eef_slow'].shape)
+ if vel_limits['eef'].shape[0] == 6:
+ vel_limits['eef'] = np.concatenate([vel_limits['eef'], 5*np.ones(10)])
+ vel_limits['eef_slow'] = np.concatenate([vel_limits['eef_slow'], 5*np.ones(10)])
+
+ super()._setup(obs_keys=obs_keys,
+ weighted_reward_keys=weighted_reward_keys,
+ reward_mode=reward_mode,
+ frame_skip=frame_skip,
+ **kwargs)
+ if init_qpos is not None:
+ self.init_qpos[:len(init_qpos)] = np.array(init_qpos)[:]
+ self.viewer_setup(distance=1.25, azimuth=-90, elevation=-20)
+
+ if self.pos_limits is not None:
+ act_low = -np.ones(self.pos_limits['eef_low'].shape[0]) if self.normalize_act else self.pos_limits['eef_low'].copy()
+ act_high = np.ones(self.pos_limits['eef_high'].shape[0]) if self.normalize_act else self.pos_limits['eef_high'].copy()
+ self.action_space = gym.spaces.Box(act_low, act_high, dtype=np.float32)
+
+ def set_joint_vel(self, jnt_vel, slow_jnt_vel):
+ if jnt_vel is not None:
+ assert(len(jnt_vel.shape)==1)
+ self.vel_limits['jnt'][:jnt_vel.shape[0]] = jnt_vel[:]
+ print('Set jnt vel to {}'.format(self.vel_limits['jnt']))
+
+ if slow_jnt_vel is not None:
+ assert(len(slow_jnt_vel.shape)==1)
+ self.vel_limits['jnt_slow'][:slow_jnt_vel.shape[0]] = slow_jnt_vel[:]
+ print('Set slow jnt vel to {}'.format(self.vel_limits['jnt_slow']))
+
+ def get_obs_dict(self, sim):
+ obs_dict = {}
+ obs_dict['time'] = np.array([self.sim.data.time])
+ obs_dict['qp'] = sim.data.qpos.copy()
+ obs_dict['qv'] = sim.data.qvel.copy()
+ obs_dict['grasp_pos'] = sim.data.site_xpos[self.grasp_sid].copy()
+ obs_dict['grasp_rot'] = mat2quat(self.sim.data.site_xmat[self.grasp_sid].reshape(3,3).transpose())
+ obs_dict['object_err'] = sim.data.site_xpos[self.object_sid]-sim.data.site_xpos[self.hand_sid]
+ obs_dict['target_err'] = np.array([np.abs(self.sim.data.site_xmat[self.object_sid][-1] - 1.0)],dtype=np.float)
+ obs_dict['object_rot'] = self.sim.data.site_xmat[self.object_sid].copy()
+ return obs_dict
+
+
+ def get_reward_dict(self, obs_dict):
+ object_dist = np.linalg.norm(obs_dict['object_err'], axis=-1)
+ target_dist = np.linalg.norm(obs_dict['target_err'], axis=-1)
+ upright = 1.0*(self.sim.data.site_xmat[self.object_sid][-1] > 0.999 and
+ (self.sim.data.site_xpos[self.object_sid][:2] >= self.pos_limits['eef_low'][:2]).all() and
+ (self.sim.data.site_xpos[self.object_sid][:2] <= self.pos_limits['eef_high'][:2]).all())
+ end_posed = 1.0*(obs_dict['qp'][0,0,8] > 0.5 and obs_dict['qp'] [0,0,8] < 1.0 and
+ obs_dict['qp'] [0,0,12] > 0.75 and obs_dict['qp'] [0,0,12] < 1.25 and
+ obs_dict['qp'] [0,0,15] > 0.5 and obs_dict['qp'] [0,0,15] < 1.0 and
+ obs_dict['grasp_pos'][0,0,2] > 1.05 and obs_dict['grasp_pos'][0,0,2] < 1.1)
+ far_th = 1.25
+
+ rwd_dict = collections.OrderedDict((
+ # Optional Keys
+ ('object_dist', object_dist),
+ ('target_dist', target_dist),
+ ('bonus', (target_dist<.01) + (target_dist<.001)),
+ ('penalty', (object_dist>far_th)),
+ # Must keys
+ ('sparse', upright*end_posed),
+ ('solved', upright*end_posed),
+ #('done', object_dist > far_th),
+ ('done', False)
+ ))
+ rwd_dict['dense'] = np.sum([wt*rwd_dict[key] for key, wt in self.rwd_keys_wt.items()], axis=0)
+ return rwd_dict
+
+ def reset(self, reset_qpos=None, reset_qvel=None, **kwargs):
+
+ if reset_qpos is None:
+ reset_qpos = self.init_qpos.copy()
+
+ if self.randomize:
+ # target location
+ self.sim.model.site_pos[self.target_sid] = self.np_random.uniform(high=self.target_xyz_range['high'], low=self.target_xyz_range['low'])
+
+ # Randomize obj pose
+ obj_jid = self.sim.model.joint_name2id(self.object_site_name)
+ reset_qpos[obj_jid:obj_jid+3] = self.np_random.uniform(low=self.obj_pos_limits['low'],
+ high=self.obj_pos_limits['high'])
+ reset_qpos[obj_jid+3:obj_jid+7] = euler2quat(self.np_random.uniform(low=(np.pi/2, np.pi/2,0), high=(np.pi/2, 2*np.pi,0)) ) # random quat
+
+ self.random_size = self.np_random.uniform(low=self.geom_sizes['low'],
+ high=self.geom_sizes['high']) # random size
+ bid = self.sim.model.body_name2id(self.object_site_name)
+ for gid in range(self.sim.model.body_geomnum[bid]):
+ gid += self.sim.model.body_geomadr[bid]
+ if gid - self.sim.model.body_geomadr[bid] < 2:
+ self.sim.model.geom_size[gid][:2] = self.random_size
+ self.sim.model.geom_pos[gid][2] = self.random_size[-1]
+ if gid - self.sim.model.body_geomadr[bid] == 1:
+ self.sim.model.geom_pos[gid][2] *= -1.0
+ else:
+ self.random_size[0] += 0.5e-4
+ elif gid - self.sim.model.body_geomadr[bid] == 2:
+ self.sim.model.geom_size[gid][0] = 0.5*self.sim.model.geom_size[gid-1][0]
+ self.sim.model.geom_pos[gid][2] = 2*self.sim.model.geom_size[gid-2][1]+self.sim.model.geom_size[gid-2][0]-0.5*self.sim.model.geom_size[gid][1]
+ elif gid - self.sim.model.body_geomadr[bid] > 2 and gid - self.sim.model.body_geomadr[bid] < 7:
+ self.sim.model.geom_pos[gid][2] = -2*self.random_size[-1]+self.sim.model.geom_size[gid][0]-0.001
+ if gid - self.sim.model.body_geomadr[bid] == 3:
+ self.sim.model.geom_pos[gid][0] = self.random_size[0] - self.sim.model.geom_size[gid][0]-0.001
+ elif gid - self.sim.model.body_geomadr[bid] == 4:
+ self.sim.model.geom_pos[gid][0] = -self.random_size[0] + self.sim.model.geom_size[gid][0] + 0.001
+ elif gid - self.sim.model.body_geomadr[bid] == 5:
+ self.sim.model.geom_pos[gid][1] = self.random_size[0] - self.sim.model.geom_size[gid][0] - 0.001
+ elif gid - self.sim.model.body_geomadr[bid] == 6:
+ self.sim.model.geom_pos[gid][1] = -self.random_size[0] + self.sim.model.geom_size[gid][0] + 0.001
+ #self.sim.model.geom_pos[gid] = self.np_random.uniform(low=-1 * self.sim.model.geom_size[gid],
+ # high=self.sim.model.geom_size[gid]) # random pos
+
+ #if (gid - self.sim.model.body_geomadr[bid] > 2 and gid - self.sim.model.body_geomadr[bid] < 7):
+ # self.sim.model.geom_rgba[gid] = self.sim.model.geom_rgba[self.sim.model.body_geomadr[bid]+1]
+ #elif (gid - self.sim.model.body_geomadr[bid] > 0 and self.np_random.rand() > 0.5):
+ # self.sim.model.geom_rgba[gid] = self.sim.model.geom_rgba[gid-1]
+ #else:
+ # self.sim.model.geom_rgba[gid][:3] = self.np_random.uniform(low=[.2, .2, .2],
+ # high=[.9, .9, .9]) # random color
+ self.sim.forward()
+
+ obs = super().reset(reset_qpos, reset_qvel, blocking=False, **kwargs)
+
+ cur_pos = self.sim.data.site_xpos[self.grasp_sid]
+ cur_rot = mat2euler(self.sim.data.site_xmat[self.grasp_sid].reshape(3,3).transpose())
+ cur_rot[np.abs(cur_rot-np.array([np.pi,0.0,0.0]))>np.abs(cur_rot+2*np.pi-np.array([np.pi,0.0,0.0]))] += 2*np.pi
+ cur_rot[np.abs(cur_rot-np.array([np.pi,0.0,0.0]))>np.abs(cur_rot-2*np.pi-np.array([np.pi,0.0,0.0]))] -= 2*np.pi
+ self.last_eef_cmd = np.concatenate([cur_pos,
+ cur_rot,
+ [self.sim.data.qpos[7]]])
+
+ return obs
+
+ def get_ik_action(self, eef_pos, eef_quat):
+ for i in range(self.max_ik):
+
+ self.ik_sim.data.qpos[:7] = np.random.normal(self.sim.data.qpos[:7], i*0.1)
+
+ self.ik_sim.data.qpos[2] = 0.0
+ self.ik_sim.data.qpos[3] = -2.0
+ self.ik_sim.forward()
+
+ ik_result = qpos_from_site_pose(physics = self.ik_sim,
+ site_name = self.sim.model.site_id2name(self.grasp_sid),
+ target_pos= eef_pos,
+ target_quat= eef_quat,
+ inplace=False,
+ regularization_strength=1.0)
+
+ if ik_result.success:
+ break
+ return ik_result
+
+ def step(self, a, **kwargs):
+ assert(len(a.shape) == 1)
+ assert(a.shape[0] == self.sim.model.nu or a.shape[0] == 16)
+
+ jnt_act_low = self.sim.model.actuator_ctrlrange[:,0].copy()
+ jnt_act_high = self.sim.model.actuator_ctrlrange[:,1].copy()
+ cur_pose = None
+
+ if a.shape[0] == self.sim.model.nu:
+ action = a
+
+ if self.normalize_act:
+ action = (0.5*action+0.5)*(jnt_act_high-jnt_act_low)+jnt_act_low
+
+ else:
+ # Un-normalize cmd
+ eef_cmd = a
+ if self.normalize_act:
+ eef_cmd = (0.5*eef_cmd+0.5)*(self.pos_limits['eef_high']-self.pos_limits['eef_low'])+self.pos_limits['eef_low']
+
+ '''
+ eef_cmd[0] = 0.5
+ eef_cmd[1] = 0.0
+ eef_cmd[2] = 1.25
+ eef_cmd[3] = -1.57
+ eef_cmd[4] = 0.0
+ eef_cmd[5] = 0.0
+ '''
+
+ eef_cmd = np.clip(eef_cmd,
+ self.pos_limits['eef_low'],
+ self.pos_limits['eef_high'])
+
+ # Get current position and rotation of eef
+ cur_rot = mat2euler(self.sim.data.site_xmat[self.grasp_sid].reshape(3,3).transpose())
+ cur_rot[np.abs(cur_rot-eef_cmd[3:6])>np.abs(cur_rot+2*np.pi-eef_cmd[3:6])] += 2*np.pi
+ cur_rot[np.abs(cur_rot-eef_cmd[3:6])>np.abs(cur_rot-2*np.pi-eef_cmd[3:6])] -= 2*np.pi
+ cur_pose = np.concatenate([self.sim.data.site_xpos[self.grasp_sid],
+ cur_rot,
+ self.sim.data.qpos[7:self.sim.model.nu]])
+
+ # Enforce cartesian velocity limits
+
+ if cur_pose[2] < self.max_slow_height and eef_cmd[2] < self.last_eef_cmd[2]:# and self.robot.is_hardware:
+ eef_cmd[:3] = np.clip(eef_cmd[:3],
+ cur_pose[:3]-self.vel_limits['eef_slow'][:3],
+ cur_pose[:3]+self.vel_limits['eef_slow'][:3])
+ else:
+ eef_cmd[:3] = np.clip(eef_cmd[:3],
+ cur_pose[:3]-self.vel_limits['eef'][:3],
+ cur_pose[:3]+self.vel_limits['eef'][:3])
+
+ # Exponential moving average to limit jerk
+ assert self.last_eef_cmd is not None
+ eef_cmd[:6] = 0.25*eef_cmd[:6] + 0.75*self.last_eef_cmd[:6]
+
+ # Prepare for IK, execute last successful command if IK fails
+ eef_pos = eef_cmd[:3]
+
+ eef_elr = eef_cmd[3:6]
+ eef_quat= euler2quat(eef_elr)
+
+ ik_result = self.get_ik_action(eef_pos, eef_quat)
+ ik_success = ik_result.success
+ if not ik_success:
+ eef_cmd = self.last_eef_cmd
+ eef_pos = eef_cmd[:3]
+ eef_elr = eef_cmd[3:6]
+ eef_quat = euler2quat(eef_elr)
+ ik_result = self.get_ik_action(eef_pos, eef_quat)
+
+ action = np.zeros(self.sim.model.nu)
+ action[:7] = ik_result.qpos[:7]
+ action[7:] = eef_cmd[6:]
+
+ self.last_eef_cmd = eef_cmd
+
+ # Enforce joint position limits
+ action = np.clip(action, jnt_act_low, jnt_act_high)
+
+ # Enforce joint velocity limits
+ if cur_pose is not None and cur_pose[2] < self.max_slow_height:
+ action = np.clip(action,
+ self.sim.data.qpos[:self.sim.model.nu]-self.vel_limits['jnt_slow'],
+ self.sim.data.qpos[:self.sim.model.nu]+self.vel_limits['jnt_slow'])
+ else:
+ action = np.clip(action,
+ self.sim.data.qpos[:self.sim.model.nu]-self.vel_limits['jnt'],
+ self.sim.data.qpos[:self.sim.model.nu]+self.vel_limits['jnt'])
+
+ if self.normalize_act:
+ action = 2*(((action - jnt_act_low)/(jnt_act_high-jnt_act_low))-0.5)
+
+
+ self.last_ctrl = self.robot.step(ctrl_desired=action,
+ ctrl_normalized=self.normalize_act,
+ step_duration=self.dt,
+ realTimeSim=self.mujoco_render_frames,
+ render_cbk=self.mj_render if self.mujoco_render_frames else None)
+ return self.forward(**kwargs)
+
+class TestPolicy():
+ def __init__(self,
+ env,
+ seed):
+ self.env = env
+ self.seed = seed
+ self.grasp_pos = None
+ self.prev = None
+
+ def get_action(self, obs):
+ obs_dict = self.env.obsvec2obsdict(np.expand_dims(obs, axis=(0,1)))
+
+ if self.grasp_pos is None:
+ self.grasp_pos = obs_dict['grasp_pos'][0, 0, :]
+ self.grasp_pos[2] = 0.875
+
+ #action = np.concatenate([self.grasp_pos, [np.pi, 0.0, 0.0], obs_dict['qp'][0, 0, 7:self.env.sim.model.nu]])
+ action = np.concatenate([self.grasp_pos, [np.pi, 0.0, 0.0], [0.0,-0.2,-0.2,-0.2,0.0,-0.2,-0.2,0.0,-0.2,-0.2]])
+ action[6:] = np.array([0.57,-0.2,1.5,0.0, # Thumb
+ 0.0,1.0,0.5, # Middle
+ 0.0,1.0,0.5]) # Pinky
+ print('obs {}, action {}'.format(obs_dict['grasp_pos'][0, 0, :], action[:3]))
+ '''
+ if self.prev is None:
+ self.prev = -2.57
+ action[6] = self.prev
+ print('act {}, obs {}'.format(action[6], obs_dict['qp'][0,0,7]))
+ if obs_dict['qp'][0,0,7] > 0.25:
+ #print('Set action -0.75')
+ self.prev = -2.57
+ elif obs_dict['qp'][0,0,7] < -1.2:
+ #print('Set action 0.75')
+ self.prev = 0.57
+ '''
+
+ action = 2*(((action - self.env.pos_limits['eef_low']) / (np.abs(self.env.pos_limits['eef_high'] - self.env.pos_limits['eef_low'])+1e-8)) - 0.5)
+ action = np.clip(action, -1, 1)
+
+ print('pol: {}'.format(action[6]))
+ return action, {'evaluation': action}
+
+class BinReorientPolicy():
+ def __init__(self,
+ env,
+ seed,
+ move_thresh=0.01,
+ begin_descent_thresh=0.05,
+ begin_grasp_thresh=0.08,
+ align_height=1.1):
+
+ self.env = env
+ self.seed = seed
+ self.yaw = 0.0
+ self.last_t = 0.0
+ self.stage = 0
+
+ self.last_qp = None
+ self.last_eef = None
+ self.move_thresh = move_thresh
+
+ self.begin_descent_thresh = begin_descent_thresh
+ self.begin_grasp_thresh = begin_grasp_thresh
+ self.align_height = align_height
+ self.gripper_close_thresh = 1e-8 if self.env.robot.is_hardware else 0.03
+ self.preplace_thresh = 0.05
+ self.real_obj_pos = np.array([0.55, 0.0, 0.875]) # 0.86
+ self.real_tar_pos = None
+
+ if self.env.robot.is_hardware:
+ self.pregrasp_config = np.array([0.57,1.0,1.5,-np.pi/2, # Thumb
+ 0.75,-0.2,-0.2, # Middle
+ -0.4,1.0,-0.2]) # Pinky
+ self.grasp_config = np.array([0.57,1.5,1.55,-np.pi/2+1.3, # Thumb
+ 0.75,-0.2,-0.2, # Middle
+ -0.4,1.55,0.3]) # Pinky
+ self.lift_config = np.array([0.57,1.5,1.55,-np.pi/2+1.3, # Thumb
+ 0.75,1.75,-0.2, # Middle
+ -0.75,1.55,0.3]) # Pinky
+ self.release_config = np.array([0.57,1.5,1.55,-np.pi/2+1.3, # Thumb
+ 0.75,1.2,-0.2, # Middle
+ -0.75,1.55,0.3]) # Pinky
+ else:
+ self.pregrasp_config = np.array([0.2,1.0,1.5,-np.pi/2, # Thumb
+ 0.75,0.0,-0.2, # Middle
+ -0.75,1.0,-0.2]) # Pinky
+ self.grasp_config = np.array([0.2,1.5,1.5,-np.pi/2, # Thumb
+ 0.75,0.0,-0.2, # Middle
+ -0.75,1.5,-0.2]) # Pinky
+ self.lift_config = np.array([0.75,1.5,1.6,-np.pi/2+0.45, # Thumb
+ 0.75,0.85,0.5, # Middle
+ -0.75,1.75,0.0]) # Pinky
+ self.release_config = np.array([0.75,1.5,1.75,-np.pi/2+0.2, # Thumb
+ 0.75,0.35,0.65, # Middle
+ -0.75,1.75,0.0]) # Pinky
+ self.done_config = np.array([0.57, 0.75, 1.55, -np.pi / 2 + 1.3, # Thumb
+ 0.75, 1.0, -0.2, # Middle
+ -0.75, 0.75, 0.3]) # Pinky
+ self.grasp_pose = None
+ self.grasp_yaw = None
+ self.grasp_count = 0
+
+ def is_moving(self, qp):
+ assert(self.last_qp is not None and qp is not None)
+ return np.linalg.norm(qp - self.last_qp[:7]) > self.move_thresh
+
+ def set_real_obj_pos(self, real_obj_pos):
+ self.real_obj_pos = real_obj_pos
+
+ def set_real_tar_pos(self, real_tar_pos):
+ self.real_tar_pos = real_tar_pos
+
+ def set_real_yaw(self, real_yaw):
+ self.yaw = real_yaw
+ while self.yaw < -np.pi:
+ self.yaw += 2*np.pi
+ while self.yaw > np.pi:
+ self.yaw -= 2*np.pi
+
+ def get_action(self, obs):
+ obs_dict = self.env.obsvec2obsdict(np.expand_dims(obs, axis=(0,1)))
+
+ if not self.env.robot.is_hardware:
+
+ obj_rot_mat = quat2mat(obs_dict['qp'][0, 0, -4:])
+ obj_yaw = np.arctan2(obj_rot_mat[0,0],obj_rot_mat[0,2])
+
+ self.yaw = obj_yaw+3*np.pi/4
+ while self.yaw < self.env.pos_limits['eef_low'][5]:
+ self.yaw += 2*np.pi
+ while self.yaw > self.env.pos_limits['eef_high'][5]:
+ self.yaw -= 2*np.pi
+
+ cur_rot_mat = quat2mat(obs_dict['grasp_rot'][0,0, :])
+
+ cur_yaw = np.arctan2(cur_rot_mat[0,0], cur_rot_mat[0,1])
+ cur_yaw -= np.pi/2.0
+
+ #while np.abs(cur_yaw-self.yaw) > np.abs(cur_yaw-2*np.pi-self.yaw):
+ # cur_yaw -= 2*np.pi
+ #while np.abs(cur_yaw-self.yaw) > np.abs(cur_yaw+2*np.pi-self.yaw):
+ # cur_yaw += 2*np.pi
+
+ while cur_yaw < self.env.pos_limits['eef_low'][5]:
+ cur_yaw += 2*np.pi
+ while cur_yaw > self.env.pos_limits['eef_high'][5]:
+ cur_yaw -= 2*np.pi
+
+ action = np.concatenate([obs_dict['grasp_pos'][0, 0, :], [np.pi, 0.0, self.yaw], obs_dict['qp'][0, 0, 7:self.env.sim.model.nu]])
+
+ if self.env.robot.is_hardware and self.real_obj_pos is not None:
+ obj_err = self.real_obj_pos-obs_dict['grasp_pos'][0, 0, :]
+ else:
+ obj_err = obs_dict['object_err'][0,0,:]
+
+ yaw_err = self.yaw - cur_yaw
+
+ if self.last_t > self.env.sim.data.time:
+ # Reset
+ self.stage = 0
+ self.last_qp = None
+ self.grasp_pose = None
+ self.last_eef = None
+ self.grasp_yaw = None
+ self.grasp_count = 0
+
+
+ elif self.stage == 0: # Wait until aligned xy
+ # Advance to next stage?
+ #print('Cur obj yaw {}, yaw err {}'.format(self.yaw-3*np.pi/4, yaw_err))
+ #print('pos err {}, yaw err {}'.format(np.linalg.norm(obj_err[:2]), np.abs(yaw_err)))
+ #print('Yaw err {}'.format(np.abs(yaw_err)))
+ if (np.linalg.norm(obj_err[:2]) < self.begin_descent_thresh and
+ np.abs(yaw_err) < 0.125
+ #(self.last_qp is not None and not self.is_moving(obs_dict['qp'][0,0,:7]))):
+ ):
+ self.stage = 1
+ self.grasp_pose = np.zeros_like(obj_err)
+ self.grasp_pose[:2] = obs_dict['grasp_pos'][0, 0, :2].copy() + obj_err[:2].copy()
+ if self.env.robot.is_hardware:
+ self.grasp_pose[0] = self.real_obj_pos[0]
+ self.grasp_pose[1] = self.real_obj_pos[1]
+ self.grasp_pose[2] = obs_dict['grasp_pos'][0, 0, 2] + 1.0*obj_err[2]
+ #0.15*np.sin(obs_dict['qp'][0, 0, 6] - 0.57)
+ #0.15*np.cos(obs_dict['qp'][0, 0, 6] - 0.57)
+ else:
+ self.grasp_pose[2] = obs_dict['grasp_pos'][0, 0, 2] + 1.2*obj_err[2]
+ self.grasp_yaw = cur_yaw
+ elif self.stage == 1:
+ if self.env.robot.is_hardware:
+ if obs_dict['grasp_pos'][0,0,2] < 0.92:
+ self.stage = 2
+ else:
+ if self.last_eef is not None and np.abs(self.last_eef[2]-obs_dict['grasp_pos'][0,0,2]) < 0.001:
+ self.stage = 3
+ self.grasp_pose[2] += 0.2
+
+ elif self.stage == 2:
+ assert(self.env.robot.is_hardware)
+ diff = obs_dict['qp'][0,0,7:17].copy()
+ diff -= self.grasp_config
+ #print('Raw {} {}'.format(obs_dict['qp'][0,0,7:17], self.grasp_config))
+ #print('Grasp err {}'.format(np.linalg.norm(diff)))
+ if np.linalg.norm(diff) < 0.45:
+ self.stage = 3
+ self.grasp_pose[2] += 0.19
+ elif self.stage == 3:
+ if self.env.robot.is_hardware:
+ #print(obs_dict['qp'][0,0,12])
+ self.grasp_count += 1
+ if obs_dict['qp'][0,0,12] > 1.55 and self.grasp_count >= 40:
+ self.stage = 4
+ self.grasp_pose[2] -= 0.04
+ self.grasp_count = 0
+ else:
+ if obj_rot_mat.flatten()[-1] > 0.95:
+ #if obs_dict['grasp_pos'][0,0,2] > self.grasp_pose[2] and obs_dict['qp'][0,0,12] > self.lift_config[5] and obs_dict['qp'][0,0,13] > self.lift_config[6]:
+ self.stage = 4
+ #self.grasp_pose[2] += 0.02
+ self.grasp_pose[2] = 1.1125
+ elif self.stage == 4:
+ #if self.env.robot.is_hardware:
+ self.grasp_count += 1
+ if self.grasp_count >= 25:
+ self.stage = 5
+
+
+ #if self.last_qp is not None:
+ # print(np.linalg.norm(self.last_qp[7:self.env.sim.model.nu] - obs_dict['qp'][0, 0, 7:self.env.sim.model.nu]))
+ self.last_t = self.env.sim.data.time
+ self.last_qp = obs_dict['qp'][0,0,:self.env.sim.model.nu]
+
+
+ #print('Stage {}, t {}'.format(self.stage, self.last_t))
+ if self.stage == 0: # Align in xy
+ if self.env.robot.is_hardware:
+ action[:2] = self.real_obj_pos[:2]
+ else:
+ action[:2] += 1.5*obj_err[0:2]
+ action[2] = self.align_height
+ action[6:] = self.pregrasp_config
+ elif self.stage == 1:
+ action[:3] = self.grasp_pose
+ action[5] = self.grasp_yaw
+ if self.env.robot.is_hardware:
+ action[6:] = self.pregrasp_config
+ else:
+ action[6:] = self.grasp_config
+ elif self.stage == 2:
+ action[:3] = self.grasp_pose
+ action[5] = self.grasp_yaw
+ action[6:] = self.grasp_config
+ elif self.stage == 3:
+ action[:3] = self.grasp_pose
+ action[5] = self.grasp_yaw
+ action[6:] = self.lift_config
+ elif self.stage == 4:
+ action[:3] = self.grasp_pose
+ action[5] = self.grasp_yaw
+ action[6:] = self.release_config
+ elif self.stage == 5:
+ action[:3] = self.grasp_pose
+ action[5] = self.grasp_yaw
+ action[6:] = self.done_config
+ #print('height {}'.format(obs_dict['grasp_pos'][0,0,2]))
+ self.last_eef = obs_dict['grasp_pos'][0,0,:].copy()
+ action = np.clip(action, self.env.pos_limits['eef_low'], self.env.pos_limits['eef_high'])
+
+ cur_rot = mat2euler(self.env.sim.data.site_xmat[self.env.grasp_sid].reshape(3,3).transpose())
+ cur_rot[np.abs(cur_rot-action[3:6])>np.abs(cur_rot+2*np.pi-action[3:6])] += 2*np.pi
+ cur_rot[np.abs(cur_rot-action[3:6])>np.abs(cur_rot-2*np.pi-action[3:6])] -= 2*np.pi
+ cur_pos = np.concatenate([self.env.sim.data.site_xpos[self.env.grasp_sid],
+ cur_rot,
+ self.env.sim.data.qpos[7:self.env.sim.model.nu]])
+ action[:3] = np.clip(action[:3], cur_pos[:3]-self.env.vel_limits['eef'][:3], cur_pos[:3]+self.env.vel_limits['eef'][:3])
+ action[6:] = np.clip(action[6:], cur_pos[6:] - self.env.vel_limits['eef'][6:],cur_pos[6:] + self.env.vel_limits['eef'][6:])
+
+ # Normalize action to be between -1 and 1
+
+ action = 2*(((action - self.env.pos_limits['eef_low']) / (np.abs(self.env.pos_limits['eef_high'] - self.env.pos_limits['eef_low'])+1e-8)) - 0.5)
+
+ action = np.clip(action, -1, 1)
+ noise_action = np.clip(action + 0.05*np.random.randn(action.shape[0]),-1,1)
+
+ return noise_action, {'evaluation': action}
diff --git a/robohive/envs/arms/franka/assets/franka_bin_pick_rp03_v0.config b/robohive/envs/arms/franka/assets/franka_bin_pick_rp03_v0.config
new file mode 100644
index 00000000..fcb4776e
--- /dev/null
+++ b/robohive/envs/arms/franka/assets/franka_bin_pick_rp03_v0.config
@@ -0,0 +1,89 @@
+{
+ # device1: sensors, actuators
+ 'franka':{
+ 'interface': {'type': 'franka', 'ip_address':'172.16.0.1', 'gain_scale': 1.5},
+ 'sensor':[
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':0, 'scale':1, 'offset':0, 'name':'fr_arm_jp1'},
+ {'range':(-1.8, 1.8), 'noise':0.05, 'hdr_id':1, 'scale':1, 'offset':0, 'name':'fr_arm_jp2'},
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':2, 'scale':1, 'offset':0, 'name':'fr_arm_jp3'},
+ {'range':(-3.1, 0.0), 'noise':0.05, 'hdr_id':3, 'scale':1, 'offset':0, 'name':'fr_arm_jp4'},
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':4, 'scale':1, 'offset':0, 'name':'fr_arm_jp5'},
+ {'range':(-1.7, 3.8), 'noise':0.05, 'hdr_id':5, 'scale':1, 'offset':-np.pi/2, 'name':'fr_arm_jp6'},
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':6, 'scale':1, 'offset':-np.pi/4, 'name':'fr_arm_jp7'},
+
+ ],
+
+ 'actuator':[
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':0, 'scale':1, 'offset':0, 'name':'panda0_joint1'},
+ {'pos_range':(-1.8326, 1.8326), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':1, 'scale':1, 'offset':0, 'name':'panda0_joint2'},
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':2, 'scale':1, 'offset':0, 'name':'panda0_joint3'},
+ {'pos_range':(-3.1416, 0.0000), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':3, 'scale':1, 'offset':0, 'name':'panda0_joint4'},
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':4, 'scale':1, 'offset':0, 'name':'panda0_joint5'},
+ {'pos_range':(-1.6600, 2.1817), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':5, 'scale':1, 'offset':np.pi/2, 'name':'panda0_joint6'},
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':6, 'scale':1, 'offset':np.pi/4, 'name':'panda0_joint7'},
+ ]
+ },
+
+ # device1: sensors, actuators
+ 'robotiq':{
+ 'interface': {'type': 'robotiq', 'ip_address':'172.16.0.3'},
+ 'sensor':[
+ {'range':(0, 0.834), 'noise':0.0, 'hdr_id':0, 'name':'robotiq_2f_85', 'scale':-9.81, 'offset':0.834},
+ ],
+ 'actuator':[
+ {'pos_range':(0, 1), 'vel_range':(-20*np.pi/4, 20*np.pi/4), 'hdr_id':0, 'name':'robotiq_2f_85', 'scale':-0.085, 'offset':0.085},
+ ]
+ },
+
+ 'right_cam':{
+ 'interface': {'type': 'realsense',
+ 'rgb_topic':'realsense_831612072257/color/image_raw',
+ 'd_topic': 'realsense_831612072257/depth_uncolored/image_raw',
+ 'data_type':'rgbd'},
+ 'sensor':[],
+ 'cam': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_raw'},
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'d', 'scale':0.05, 'offset':0, 'name':'/depth_mono/image_raw'},
+ ],
+ 'actuator':[]
+ },
+
+ 'left_cam':{
+ 'interface': {'type': 'realsense',
+ 'rgb_topic':'realsense_815412070729/color/image_raw',
+ 'd_topic':'realsense_815412070729/depth_uncolored/image_raw',
+ 'data_type':'rgbd'},
+ 'sensor':[],
+ 'cam': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_raw'},
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'d', 'scale':0.05, 'offset':0, 'name':'/depth_mono/image_raw'},
+ ],
+ 'actuator':[]
+ },
+
+ 'top_cam':{
+ 'interface': {'type': 'realsense',
+ 'rgb_topic':'realsense_831612071119/color/image_raw',
+ 'd_topic': 'realsense_831612071119/depth_uncolored/image_raw',
+ 'data_type':'rgbd'},
+ 'sensor':[],
+ 'cam': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_color'},
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'d', 'scale':0.05, 'offset':0, 'name':'/depth_mono/image_raw'},
+ ],
+ 'actuator':[]
+ },
+
+ 'Franka_wrist_cam':{
+ 'interface': {'type': 'realsense',
+ 'rgb_topic':'realsense_814412072030/color/image_raw',
+ 'd_topic': 'realsense_814412072030/depth_uncolored/image_raw',
+ 'data_type':'rgbd'},
+ 'sensor':[],
+ 'cam': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_color'},
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'d', 'scale':0.05, 'offset':0, 'name':'/depth_mono/image_raw'},
+ ],
+ 'actuator':[]
+ },
+}
diff --git a/robohive/envs/arms/franka/assets/franka_bin_pick_rp05_v0.config b/robohive/envs/arms/franka/assets/franka_bin_pick_rp05_v0.config
new file mode 100644
index 00000000..5014a4ad
--- /dev/null
+++ b/robohive/envs/arms/franka/assets/franka_bin_pick_rp05_v0.config
@@ -0,0 +1,89 @@
+{
+ # device1: sensors, actuators
+ 'franka':{
+ 'interface': {'type': 'franka', 'ip_address':'172.16.0.1', 'gain_scale': 1.5},
+ 'sensor':[
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':0, 'scale':1, 'offset':0, 'name':'fr_arm_jp1'},
+ {'range':(-1.8, 1.8), 'noise':0.05, 'hdr_id':1, 'scale':1, 'offset':0, 'name':'fr_arm_jp2'},
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':2, 'scale':1, 'offset':0, 'name':'fr_arm_jp3'},
+ {'range':(-3.1, 0.0), 'noise':0.05, 'hdr_id':3, 'scale':1, 'offset':0, 'name':'fr_arm_jp4'},
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':4, 'scale':1, 'offset':0, 'name':'fr_arm_jp5'},
+ {'range':(-1.7, 3.8), 'noise':0.05, 'hdr_id':5, 'scale':1, 'offset':-np.pi/2, 'name':'fr_arm_jp6'},
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':6, 'scale':1, 'offset':-np.pi/4, 'name':'fr_arm_jp7'},
+
+ ],
+
+ 'actuator':[
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':0, 'scale':1, 'offset':0, 'name':'panda0_joint1'},
+ {'pos_range':(-1.8326, 1.8326), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':1, 'scale':1, 'offset':0, 'name':'panda0_joint2'},
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':2, 'scale':1, 'offset':0, 'name':'panda0_joint3'},
+ {'pos_range':(-3.1416, 0.0000), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':3, 'scale':1, 'offset':0, 'name':'panda0_joint4'},
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':4, 'scale':1, 'offset':0, 'name':'panda0_joint5'},
+ {'pos_range':(-1.6600, 2.1817), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':5, 'scale':1, 'offset':np.pi/2, 'name':'panda0_joint6'},
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':6, 'scale':1, 'offset':np.pi/4, 'name':'panda0_joint7'},
+ ]
+ },
+
+ # device1: sensors, actuators
+ 'robotiq':{
+ 'interface': {'type': 'robotiq', 'ip_address':'172.16.0.3'},
+ 'sensor':[
+ {'range':(0, 0.834), 'noise':0.0, 'hdr_id':0, 'name':'robotiq_2f_85', 'scale':-9.81, 'offset':0.834},
+ ],
+ 'actuator':[
+ {'pos_range':(0, 1), 'vel_range':(-20*np.pi/4, 20*np.pi/4), 'hdr_id':0, 'name':'robotiq_2f_85', 'scale':-0.085, 'offset':0.085},
+ ]
+ },
+
+ 'right_cam':{
+ 'interface': {'type': 'realsense',
+ 'rgb_topic':'realsense_818312071351/color/image_raw',
+ 'd_topic': 'realsense_818312071351/depth_uncolored/image_raw',
+ 'data_type':'rgbd'},
+ 'sensor':[],
+ 'cam': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_raw'},
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'d', 'scale':0.05, 'offset':0, 'name':'/depth_mono/image_raw'},
+ ],
+ 'actuator':[]
+ },
+
+ 'left_cam':{
+ 'interface': {'type': 'realsense',
+ 'rgb_topic':'realsense_745412071685/color/image_raw',
+ 'd_topic':'realsense_745412071685/depth_uncolored/image_raw',
+ 'data_type':'rgbd'},
+ 'sensor':[],
+ 'cam': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_raw'},
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'d', 'scale':0.05, 'offset':0, 'name':'/depth_mono/image_raw'},
+ ],
+ 'actuator':[]
+ },
+
+ 'top_cam':{
+ 'interface': {'type': 'realsense',
+ 'rgb_topic':'realsense_815412070225/color/image_raw',
+ 'd_topic': 'realsense_815412070225/depth_uncolored/image_raw',
+ 'data_type':'rgbd'},
+ 'sensor':[],
+ 'cam': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_color'},
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'d', 'scale':0.05, 'offset':0, 'name':'/depth_mono/image_raw'},
+ ],
+ 'actuator':[]
+ },
+
+ 'Franka_wrist_cam':{
+ 'interface': {'type': 'realsense',
+ 'rgb_topic':'realsense_135122076787/color/image_raw',
+ 'd_topic': 'realsense_135122076787/depth_uncolored/image_raw',
+ 'data_type':'rgbd'},
+ 'sensor':[],
+ 'cam': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_color'},
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'d', 'scale':0.05, 'offset':0, 'name':'/depth_mono/image_raw'},
+ ],
+ 'actuator':[]
+ },
+}
diff --git a/robohive/envs/arms/franka/assets/franka_bin_pick_v0.config b/robohive/envs/arms/franka/assets/franka_bin_pick_v0.config
new file mode 100644
index 00000000..c3f44300
--- /dev/null
+++ b/robohive/envs/arms/franka/assets/franka_bin_pick_v0.config
@@ -0,0 +1,89 @@
+{
+ # device1: sensors, actuators
+ 'franka':{
+ 'interface': {'type': 'franka', 'ip_address':'172.16.0.1', 'gain_scale': 1.5},
+ 'sensor':[
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':0, 'scale':1, 'offset':0, 'name':'fr_arm_jp1'},
+ {'range':(-1.8, 1.8), 'noise':0.05, 'hdr_id':1, 'scale':1, 'offset':0, 'name':'fr_arm_jp2'},
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':2, 'scale':1, 'offset':0, 'name':'fr_arm_jp3'},
+ {'range':(-3.1, 0.0), 'noise':0.05, 'hdr_id':3, 'scale':1, 'offset':0, 'name':'fr_arm_jp4'},
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':4, 'scale':1, 'offset':0, 'name':'fr_arm_jp5'},
+ {'range':(-1.7, 3.8), 'noise':0.05, 'hdr_id':5, 'scale':1, 'offset':-np.pi/2, 'name':'fr_arm_jp6'},
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':6, 'scale':1, 'offset':-np.pi/4, 'name':'fr_arm_jp7'},
+
+ ],
+
+ 'actuator':[
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':0, 'scale':1, 'offset':0, 'name':'panda0_joint1'},
+ {'pos_range':(-1.8326, 1.8326), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':1, 'scale':1, 'offset':0, 'name':'panda0_joint2'},
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':2, 'scale':1, 'offset':0, 'name':'panda0_joint3'},
+ {'pos_range':(-3.1416, 0.0000), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':3, 'scale':1, 'offset':0, 'name':'panda0_joint4'},
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':4, 'scale':1, 'offset':0, 'name':'panda0_joint5'},
+ {'pos_range':(-1.6600, 2.1817), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':5, 'scale':1, 'offset':np.pi/2, 'name':'panda0_joint6'},
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':6, 'scale':1, 'offset':np.pi/4, 'name':'panda0_joint7'},
+ ]
+ },
+
+ # device1: sensors, actuators
+ 'robotiq':{
+ 'interface': {'type': 'robotiq', 'ip_address':'172.16.0.3'},
+ 'sensor':[
+ {'range':(0, 0.834), 'noise':0.0, 'hdr_id':0, 'name':'robotiq_2f_85', 'scale':-9.81, 'offset':0.834},
+ ],
+ 'actuator':[
+ {'pos_range':(0, 1), 'vel_range':(-20*np.pi/4, 20*np.pi/4), 'hdr_id':0, 'name':'robotiq_2f_85', 'scale':-0.085, 'offset':0.085},
+ ]
+ },
+
+ 'right_cam':{
+ 'interface': {'type': 'realsense',
+ 'rgb_topic':'realsense_817612071438/color/image_raw',
+ 'd_topic': 'realsense_817612071438/depth_uncolored/image_raw',
+ 'data_type':'rgbd'},
+ 'sensor':[],
+ 'cam': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_raw'},
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'d', 'scale':0.05, 'offset':0, 'name':'/depth_mono/image_raw'},
+ ],
+ 'actuator':[]
+ },
+
+ 'left_cam':{
+ 'interface': {'type': 'realsense',
+ 'rgb_topic':'realsense_923322071682/color/image_raw',
+ 'd_topic':'realsense_923322071682/depth_uncolored/image_raw',
+ 'data_type':'rgbd'},
+ 'sensor':[],
+ 'cam': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_raw'},
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'d', 'scale':0.05, 'offset':0, 'name':'/depth_mono/image_raw'},
+ ],
+ 'actuator':[]
+ },
+
+ 'top_cam':{
+ 'interface': {'type': 'realsense',
+ 'rgb_topic':'realsense_831612071935/color/image_raw',
+ 'd_topic': 'realsense_831612071935/depth_uncolored/image_raw',
+ 'data_type':'rgbd'},
+ 'sensor':[],
+ 'cam': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_color'},
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'d', 'scale':0.05, 'offset':0, 'name':'/depth_mono/image_raw'},
+ ],
+ 'actuator':[]
+ },
+
+ 'Franka_wrist_cam':{
+ 'interface': {'type': 'realsense',
+ 'rgb_topic':'realsense_936322070059/color/image_raw',
+ 'd_topic': 'realsense_936322070059/depth_uncolored/image_raw',
+ 'data_type':'rgbd'},
+ 'sensor':[],
+ 'cam': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_color'},
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'d', 'scale':0.05, 'offset':0, 'name':'/depth_mono/image_raw'},
+ ],
+ 'actuator':[]
+ },
+}
\ No newline at end of file
diff --git a/robohive/envs/arms/franka/assets/franka_bin_pick_v0.xml b/robohive/envs/arms/franka/assets/franka_bin_pick_v0.xml
new file mode 100644
index 00000000..329dc1e7
--- /dev/null
+++ b/robohive/envs/arms/franka/assets/franka_bin_pick_v0.xml
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/robohive/envs/arms/franka/assets/franka_bin_push_teleop_v0.xml b/robohive/envs/arms/franka/assets/franka_bin_push_teleop_v0.xml
new file mode 100644
index 00000000..dd58fe95
--- /dev/null
+++ b/robohive/envs/arms/franka/assets/franka_bin_push_teleop_v0.xml
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/robohive/envs/arms/franka/assets/franka_bin_push_v0.config b/robohive/envs/arms/franka/assets/franka_bin_push_v0.config
new file mode 100644
index 00000000..b2df73dc
--- /dev/null
+++ b/robohive/envs/arms/franka/assets/franka_bin_push_v0.config
@@ -0,0 +1,89 @@
+{
+ # device1: sensors, actuators
+ 'franka':{
+ 'interface': {'type': 'franka', 'ip_address':'172.16.0.1', 'gain_scale': 1.0},
+ 'sensor':[
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':0, 'scale':1, 'offset':0, 'name':'fr_arm_jp1'},
+ {'range':(-1.8, 1.8), 'noise':0.05, 'hdr_id':1, 'scale':1, 'offset':0, 'name':'fr_arm_jp2'},
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':2, 'scale':1, 'offset':0, 'name':'fr_arm_jp3'},
+ {'range':(-3.1, 0.0), 'noise':0.05, 'hdr_id':3, 'scale':1, 'offset':0, 'name':'fr_arm_jp4'},
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':4, 'scale':1, 'offset':0, 'name':'fr_arm_jp5'},
+ {'range':(-1.7, 3.8), 'noise':0.05, 'hdr_id':5, 'scale':1, 'offset':-np.pi/2, 'name':'fr_arm_jp6'},
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':6, 'scale':1, 'offset':-np.pi/4, 'name':'fr_arm_jp7'},
+
+ ],
+
+ 'actuator':[
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':0, 'scale':1, 'offset':0, 'name':'panda0_joint1'},
+ {'pos_range':(-1.8326, 1.8326), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':1, 'scale':1, 'offset':0, 'name':'panda0_joint2'},
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':2, 'scale':1, 'offset':0, 'name':'panda0_joint3'},
+ {'pos_range':(-3.1416, 0.0000), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':3, 'scale':1, 'offset':0, 'name':'panda0_joint4'},
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':4, 'scale':1, 'offset':0, 'name':'panda0_joint5'},
+ {'pos_range':(-1.6600, 2.1817), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':5, 'scale':1, 'offset':np.pi/2, 'name':'panda0_joint6'},
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':6, 'scale':1, 'offset':np.pi/4, 'name':'panda0_joint7'},
+ ]
+ },
+
+ 'robotiq':{
+ 'interface': {'type': 'robotiq', 'ip_address':'172.16.0.3'},
+ 'sensor':[
+ {'range':(0, 0.834), 'noise':0.0, 'hdr_id':0, 'name':'robotiq_2f_85', 'scale':-9.81, 'offset':0.834},
+ ],
+ 'actuator':[
+ {'pos_range':(0, 1), 'vel_range':(-20*np.pi/4, 20*np.pi/4), 'hdr_id':0, 'name':'robotiq_2f_85', 'scale':-0.085, 'offset':0.085},
+ ]
+ },
+
+ 'right_cam':{
+ 'interface': {'type': 'realsense',
+ 'rgb_topic':'realsense_819112073358/color/image_raw',
+ 'd_topic': 'realsense_819112073358/depth_uncolored/image_raw',
+ 'data_type':'rgbd'},
+ 'sensor':[],
+ 'cam': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_raw'},
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'d', 'scale':0.05, 'offset':0, 'name':'/depth_mono/image_raw'},
+ ],
+ 'actuator':[]
+ },
+
+ 'left_cam':{
+ 'interface': {'type': 'realsense',
+ 'rgb_topic':'realsense_948522071060/color/image_raw',
+ 'd_topic':'realsense_948522071060/depth_uncolored/image_raw',
+ 'data_type':'rgbd'},
+ 'sensor':[],
+ 'cam': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_raw'},
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'d', 'scale':0.05, 'offset':0, 'name':'/depth_mono/image_raw'},
+ ],
+ 'actuator':[]
+ },
+
+ 'top_cam':{
+ 'interface': {'type': 'realsense',
+ 'rgb_topic':'realsense_815412071252/color/image_raw',
+ 'd_topic': 'realsense_815412071252/depth_uncolored/image_raw',
+ 'data_type':'rgbd'},
+ 'sensor':[],
+ 'cam': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_raw'},
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'d', 'scale':0.05, 'offset':0, 'name':'/depth_mono/image_raw'},
+ ],
+ 'actuator':[]
+ },
+
+ 'Franka_wrist_cam':{
+ 'interface': {'type': 'realsense',
+ 'rgb_topic':'realsense_137222072789/color/image_raw',
+ 'd_topic': 'realsense_137222072789/depth_uncolored/image_raw',
+ 'data_type':'rgbd'},
+ 'sensor':[],
+ 'cam': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_raw'},
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'d', 'scale':0.05, 'offset':0, 'name':'/depth_mono/image_raw'},
+ ],
+ 'actuator':[]
+ },
+
+}
diff --git a/robohive/envs/arms/franka/assets/franka_bin_push_v0.xml b/robohive/envs/arms/franka/assets/franka_bin_push_v0.xml
new file mode 100644
index 00000000..64841e94
--- /dev/null
+++ b/robohive/envs/arms/franka/assets/franka_bin_push_v0.xml
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/robohive/envs/arms/franka/assets/franka_dmanus_reorient_real_v0.config b/robohive/envs/arms/franka/assets/franka_dmanus_reorient_real_v0.config
new file mode 100644
index 00000000..5b9506ba
--- /dev/null
+++ b/robohive/envs/arms/franka/assets/franka_dmanus_reorient_real_v0.config
@@ -0,0 +1,109 @@
+{
+
+ # device1: sensors, actuators
+ 'franka':{
+ 'interface': {'type': 'franka', 'ip_address':'172.16.0.1', 'gain_scale':1.5},
+ 'sensor':[
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':0, 'scale':1, 'offset':0, 'name':'fr_arm_jp1'},
+ {'range':(-1.8, 1.8), 'noise':0.05, 'hdr_id':1, 'scale':1, 'offset':0, 'name':'fr_arm_jp2'},
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':2, 'scale':1, 'offset':0, 'name':'fr_arm_jp3'},
+ {'range':(-3.1, 0.0), 'noise':0.05, 'hdr_id':3, 'scale':1, 'offset':0, 'name':'fr_arm_jp4'},
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':4, 'scale':1, 'offset':0, 'name':'fr_arm_jp5'},
+ {'range':(-1.7, 3.8), 'noise':0.05, 'hdr_id':5, 'scale':1, 'offset':-np.pi/2, 'name':'fr_arm_jp6'},
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':6, 'scale':1, 'offset':-np.pi/4, 'name':'fr_arm_jp7'},
+ ],
+
+ 'actuator':[
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':0, 'scale':1, 'offset':0, 'name':'panda0_joint1'},
+ {'pos_range':(-1.8326, 1.8326), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':1, 'scale':1, 'offset':0, 'name':'panda0_joint2'},
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':2, 'scale':1, 'offset':0, 'name':'panda0_joint3'},
+ {'pos_range':(-3.1416, 0.0000), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':3, 'scale':1, 'offset':0, 'name':'panda0_joint4'},
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':4, 'scale':1, 'offset':0, 'name':'panda0_joint5'},
+ {'pos_range':(-1.6600, 2.1817), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':5, 'scale':1, 'offset':np.pi/2, 'name':'panda0_joint6'},
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':6, 'scale':1, 'offset':np.pi/4, 'name':'panda0_joint7'},
+ ]
+ },
+
+ # device1: sensors, actuators
+ 'dmanus':{
+ 'interface': {'type': 'dynamixel', 'motor_type':"X", 'name':"/dev/ttyUSB0"},
+ 'sensor':[
+ {'range':(-2.57, 0.57), 'noise':0.05, 'hdr_id':30, 'name':'TF_ADB_jp', 'scale':-1, 'offset':np.pi },
+ {'range':(-0.00, 2.14), 'noise':0.05, 'hdr_id':31, 'name':'TF_MCP_jp', 'scale':-1, 'offset':3*np.pi/2 },
+ {'range':(-0.00, 2.14), 'noise':0.05, 'hdr_id':32, 'name':'TF_PIP_jp', 'scale':-1, 'offset':np.pi },
+ {'range':(-1.57, 2.00), 'noise':0.05, 'hdr_id':33, 'name':'TF_DIP_jp', 'scale':-1, 'offset':3*np.pi/2 },
+ {'range':(-0.75, 0.57), 'noise':0.05, 'hdr_id':20, 'name':'FF_ADB_jp', 'scale':-1, 'offset':np.pi },
+ {'range':(-0.00, 2.14), 'noise':0.05, 'hdr_id':21, 'name':'FF_MCP_jp', 'scale':-1, 'offset':3*np.pi/2-0.3 },
+ {'range':(-0.00, 2.00), 'noise':0.05, 'hdr_id':22, 'name':'FF_PIP_jp', 'scale':-1, 'offset':np.pi },
+ {'range':(-0.75, 0.57), 'noise':0.05, 'hdr_id':10, 'name':'PF_ADB_jp', 'scale':-1, 'offset':np.pi },
+ {'range':(-0.00, 2.14), 'noise':0.05, 'hdr_id':11, 'name':'PF_MCP_jp', 'scale':-1, 'offset':3*np.pi/2 },
+ {'range':(-0.00, 2.00), 'noise':0.05, 'hdr_id':12, 'name':'PF_PIP_jp', 'scale':-1, 'offset':np.pi },
+
+ ],
+ 'actuator':[
+ {'pos_range':(-2.57, 0.57), 'vel_range':(-2*np.pi/4, 2*np.pi/4), 'hdr_id':30, 'name':'TF_ADB', 'mode':'Position', 'scale':-1, 'offset':np.pi },
+ {'pos_range':(-0.00, 2.14), 'vel_range':(-2*np.pi/4, 2*np.pi/4), 'hdr_id':31, 'name':'TF_MCP', 'mode':'Position', 'scale':-1, 'offset':3*np.pi/2 },
+ {'pos_range':(-0.00, 2.14), 'vel_range':(-2*np.pi/4, 2*np.pi/4), 'hdr_id':32, 'name':'TF_PIP', 'mode':'Position', 'scale':-1, 'offset':np.pi },
+ {'pos_range':(-1.57, 2.00), 'vel_range':(-2*np.pi/4, 2*np.pi/4), 'hdr_id':33, 'name':'TF_DIP', 'mode':'Position', 'scale':-1, 'offset':3*np.pi/2 },
+ {'pos_range':(-0.75, 0.57), 'vel_range':(-2*np.pi/4, 2*np.pi/4), 'hdr_id':20, 'name':'FF_ADB', 'mode':'Position', 'scale':-1, 'offset':np.pi },
+ {'pos_range':(-0.00, 2.14), 'vel_range':(-2*np.pi/4, 2*np.pi/4), 'hdr_id':21, 'name':'FF_MCP', 'mode':'Position', 'scale':-1, 'offset':3*np.pi/2.0-0.3},
+ {'pos_range':(-0.00, 2.00), 'vel_range':(-2*np.pi/4, 2*np.pi/4), 'hdr_id':22, 'name':'FF_PIP', 'mode':'Position', 'scale':-1, 'offset':np.pi },
+ {'pos_range':(-0.75, 0.57), 'vel_range':(-2*np.pi/4, 2*np.pi/4), 'hdr_id':10, 'name':'PF_ADB', 'mode':'Position', 'scale':-1, 'offset':np.pi },
+ {'pos_range':(-0.00, 2.14), 'vel_range':(-2*np.pi/4, 2*np.pi/4), 'hdr_id':11, 'name':'PF_MCP', 'mode':'Position', 'scale':-1, 'offset':3*np.pi/2 },
+ {'pos_range':(-0.00, 2.00), 'vel_range':(-2*np.pi/4, 2*np.pi/4), 'hdr_id':12, 'name':'PF_PIP', 'mode':'Position', 'scale':-1, 'offset':np.pi },
+ ]
+ },
+
+ 'right_cam':{
+ 'interface': {'type': 'realsense',
+ 'rgb_topic':'realsense_138422075994/color/image_raw',
+ 'd_topic': 'realsense_138422075994/depth_uncolored/image_raw',
+ 'data_type':'rgbd'},
+ 'sensor':[],
+ 'cam': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_raw'},
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'d', 'scale':0.05, 'offset':0, 'name':'/depth_mono/image_raw'},
+ ],
+ 'actuator':[]
+ },
+
+ 'left_cam':{
+ 'interface': {'type': 'realsense',
+ 'rgb_topic':'realsense_815412070347/color/image_raw',
+ 'd_topic':'realsense_815412070347/depth_uncolored/image_raw',
+ 'data_type':'rgbd'},
+ 'sensor':[],
+ 'cam': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_raw'},
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'d', 'scale':0.05, 'offset':0, 'name':'/depth_mono/image_raw'},
+ ],
+ 'actuator':[]
+ },
+
+ 'top_cam':{
+ 'interface': {'type': 'realsense',
+ 'rgb_topic':'realsense_815412070804/color/image_raw',
+ 'd_topic': 'realsense_815412070804/depth_uncolored/image_raw',
+ 'data_type':'rgbd'},
+ 'sensor':[],
+ 'cam': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_color'},
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'d', 'scale':0.05, 'offset':0, 'name':'/depth_mono/image_raw'},
+ ],
+ 'actuator':[]
+ },
+
+ #'Franka_wrist_cam':{
+ # 'interface': {'type': 'realsense',
+ # 'rgb_topic':'realsense_827112071730/color/image_raw',
+ # 'd_topic': 'realsense_827112071730/depth_uncolored/image_raw',
+ # 'data_type':'rgbd'},
+ # 'sensor':[],
+ # 'cam': [
+ # {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_color'},
+ # {'range':(0, 255), 'noise':0.00, 'hdr_id':'d', 'scale':0.05, 'offset':0, 'name':'/depth_mono/image_raw'},
+ # ],
+ # 'actuator':[]
+ #},
+
+}
diff --git a/robohive/envs/arms/franka/assets/franka_dmanus_reorient_sim_v0.config b/robohive/envs/arms/franka/assets/franka_dmanus_reorient_sim_v0.config
new file mode 100644
index 00000000..48b7dd37
--- /dev/null
+++ b/robohive/envs/arms/franka/assets/franka_dmanus_reorient_sim_v0.config
@@ -0,0 +1,109 @@
+{
+
+ # device1: sensors, actuators
+ 'franka':{
+ 'interface': {'type': 'franka', 'ip_address':'172.16.0.1', 'gain_scale':1.0},
+ 'sensor':[
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':0, 'scale':1, 'offset':0, 'name':'fr_arm_jp1'},
+ {'range':(-1.8, 1.8), 'noise':0.05, 'hdr_id':1, 'scale':1, 'offset':0, 'name':'fr_arm_jp2'},
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':2, 'scale':1, 'offset':0, 'name':'fr_arm_jp3'},
+ {'range':(-3.1, 0.0), 'noise':0.05, 'hdr_id':3, 'scale':1, 'offset':0, 'name':'fr_arm_jp4'},
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':4, 'scale':1, 'offset':0, 'name':'fr_arm_jp5'},
+ {'range':(-1.7, 3.8), 'noise':0.05, 'hdr_id':5, 'scale':1, 'offset':-np.pi/2, 'name':'fr_arm_jp6'},
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':6, 'scale':1, 'offset':-np.pi/4, 'name':'fr_arm_jp7'},
+ ],
+
+ 'actuator':[
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':0, 'scale':1, 'offset':0, 'name':'panda0_joint1'},
+ {'pos_range':(-1.8326, 1.8326), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':1, 'scale':1, 'offset':0, 'name':'panda0_joint2'},
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':2, 'scale':1, 'offset':0, 'name':'panda0_joint3'},
+ {'pos_range':(-3.1416, 0.0000), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':3, 'scale':1, 'offset':0, 'name':'panda0_joint4'},
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':4, 'scale':1, 'offset':0, 'name':'panda0_joint5'},
+ {'pos_range':(-1.6600, 2.1817), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':5, 'scale':1, 'offset':np.pi/2, 'name':'panda0_joint6'},
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':6, 'scale':1, 'offset':np.pi/4, 'name':'panda0_joint7'},
+ ]
+ },
+
+ # device1: sensors, actuators
+ 'dmanus':{
+ 'interface': {'type': 'dynamixel', 'motor_type':"X", 'name':"/dev/ttyUSB0"},
+ 'sensor':[
+ {'range':(-2.57, 0.57), 'noise':0.05, 'hdr_id':30, 'name':'TF_ADB_jp', 'scale':-1, 'offset':3*np.pi/4 },
+ {'range':(-0.00, 2.14), 'noise':0.05, 'hdr_id':31, 'name':'TF_MCP_jp', 'scale':-1, 'offset':3*np.pi/2 },
+ {'range':(-0.00, 2.14), 'noise':0.05, 'hdr_id':32, 'name':'TF_PIP_jp', 'scale':-1, 'offset':np.pi },
+ {'range':(-1.57, 2.00), 'noise':0.05, 'hdr_id':33, 'name':'TF_DIP_jp', 'scale':-1, 'offset':np.pi },
+ {'range':(-0.75, 0.57), 'noise':0.05, 'hdr_id':20, 'name':'FF_ADB_jp', 'scale':-1, 'offset':np.pi },
+ {'range':(-0.00, 2.14), 'noise':0.05, 'hdr_id':21, 'name':'FF_MCP_jp', 'scale':-1, 'offset':3*np.pi/2-0.3 },
+ {'range':(-0.00, 2.00), 'noise':0.05, 'hdr_id':22, 'name':'FF_PIP_jp', 'scale':-1, 'offset':np.pi },
+ {'range':(-0.75, 0.57), 'noise':0.05, 'hdr_id':10, 'name':'PF_ADB_jp', 'scale':-1, 'offset':np.pi },
+ {'range':(-0.00, 2.14), 'noise':0.05, 'hdr_id':11, 'name':'PF_MCP_jp', 'scale':-1, 'offset':3*np.pi/2 },
+ {'range':(-0.00, 2.00), 'noise':0.05, 'hdr_id':12, 'name':'PF_PIP_jp', 'scale':-1, 'offset':np.pi },
+
+ ],
+ 'actuator':[
+ {'pos_range':(-2.57, 0.57), 'vel_range':(-2*np.pi/4, 2*np.pi/4), 'hdr_id':30, 'name':'TF_ADB', 'mode':'Position', 'scale':-1, 'offset':3*np.pi/4 },
+ {'pos_range':(-0.00, 2.14), 'vel_range':(-2*np.pi/4, 2*np.pi/4), 'hdr_id':31, 'name':'TF_MCP', 'mode':'Position', 'scale':-1, 'offset':3*np.pi/2 },
+ {'pos_range':(-0.00, 2.14), 'vel_range':(-2*np.pi/4, 2*np.pi/4), 'hdr_id':32, 'name':'TF_PIP', 'mode':'Position', 'scale':-1, 'offset':np.pi },
+ {'pos_range':(-0.00, 2.00), 'vel_range':(-2*np.pi/4, 2*np.pi/4), 'hdr_id':33, 'name':'TF_DIP', 'mode':'Position', 'scale':-1, 'offset':np.pi },
+ {'pos_range':(-0.75, 0.57), 'vel_range':(-2*np.pi/4, 2*np.pi/4), 'hdr_id':20, 'name':'FF_ADB', 'mode':'Position', 'scale':-1, 'offset':np.pi },
+ {'pos_range':(-0.00, 2.14), 'vel_range':(-2*np.pi/4, 2*np.pi/4), 'hdr_id':21, 'name':'FF_MCP', 'mode':'Position', 'scale':-1, 'offset':3*np.pi/2.0-0.3},
+ {'pos_range':(-0.00, 2.00), 'vel_range':(-2*np.pi/4, 2*np.pi/4), 'hdr_id':22, 'name':'FF_PIP', 'mode':'Position', 'scale':-1, 'offset':np.pi },
+ {'pos_range':(-0.75, 0.57), 'vel_range':(-2*np.pi/4, 2*np.pi/4), 'hdr_id':10, 'name':'PF_ADB', 'mode':'Position', 'scale':-1, 'offset':np.pi },
+ {'pos_range':(-0.00, 2.14), 'vel_range':(-2*np.pi/4, 2*np.pi/4), 'hdr_id':11, 'name':'PF_MCP', 'mode':'Position', 'scale':-1, 'offset':3*np.pi/2 },
+ {'pos_range':(-0.00, 2.00), 'vel_range':(-2*np.pi/4, 2*np.pi/4), 'hdr_id':12, 'name':'PF_PIP', 'mode':'Position', 'scale':-1, 'offset':np.pi },
+ ]
+ },
+
+ 'right_cam':{
+ 'interface': {'type': 'realsense',
+ 'rgb_topic':'realsense_138422075994/color/image_raw',
+ 'd_topic': 'realsense_138422075994/depth_uncolored/image_raw',
+ 'data_type':'rgbd'},
+ 'sensor':[],
+ 'cam': [
+ {'range':(0, 255), 'noise':25, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_raw'},
+ {'range':(0, 255), 'noise':0.005, 'hdr_id':'d', 'scale':0.05, 'offset':0, 'name':'/depth_mono/image_raw'},
+ ],
+ 'actuator':[]
+ },
+
+ 'left_cam':{
+ 'interface': {'type': 'realsense',
+ 'rgb_topic':'realsense_815412070347/color/image_raw',
+ 'd_topic':'realsense_815412070347/depth_uncolored/image_raw',
+ 'data_type':'rgbd'},
+ 'sensor':[],
+ 'cam': [
+ {'range':(0, 255), 'noise':25, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_raw'},
+ {'range':(0, 255), 'noise':0.005, 'hdr_id':'d', 'scale':0.05, 'offset':0, 'name':'/depth_mono/image_raw'},
+ ],
+ 'actuator':[]
+ },
+
+ 'top_cam':{
+ 'interface': {'type': 'realsense',
+ 'rgb_topic':'realsense_815412070804/color/image_raw',
+ 'd_topic': 'realsense_815412070804/depth_uncolored/image_raw',
+ 'data_type':'rgbd'},
+ 'sensor':[],
+ 'cam': [
+ {'range':(0, 255), 'noise':25, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_color'},
+ {'range':(0, 255), 'noise':0.005, 'hdr_id':'d', 'scale':0.05, 'offset':0, 'name':'/depth_mono/image_raw'},
+ ],
+ 'actuator':[]
+ },
+
+ #'Franka_wrist_cam':{
+ # 'interface': {'type': 'realsense',
+ # 'rgb_topic':'realsense_827112071730/color/image_raw',
+ # 'd_topic': 'realsense_827112071730/depth_uncolored/image_raw',
+ # 'data_type':'rgbd'},
+ # 'sensor':[],
+ # 'cam': [
+ # {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_color'},
+ # {'range':(0, 255), 'noise':0.00, 'hdr_id':'d', 'scale':0.05, 'offset':0, 'name':'/depth_mono/image_raw'},
+ # ],
+ # 'actuator':[]
+ #},
+
+}
\ No newline at end of file
diff --git a/robohive/envs/arms/franka/assets/franka_dmanus_reorient_v0.xml b/robohive/envs/arms/franka/assets/franka_dmanus_reorient_v0.xml
new file mode 100644
index 00000000..1668e639
--- /dev/null
+++ b/robohive/envs/arms/franka/assets/franka_dmanus_reorient_v0.xml
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ # To introduce asymmetries in contact between bottom of object and bin
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/robohive/envs/arms/franka/assets/franka_hang_push_v0.config b/robohive/envs/arms/franka/assets/franka_hang_push_v0.config
new file mode 100644
index 00000000..75c41666
--- /dev/null
+++ b/robohive/envs/arms/franka/assets/franka_hang_push_v0.config
@@ -0,0 +1,89 @@
+{
+ # device1: sensors, actuators
+ 'franka':{
+ 'interface': {'type': 'franka', 'ip_address':'172.16.0.1', 'gain_scale': 0.5},
+ 'sensor':[
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':0, 'scale':1, 'offset':0, 'name':'fr_arm_jp1'},
+ {'range':(-1.8, 1.8), 'noise':0.05, 'hdr_id':1, 'scale':1, 'offset':0, 'name':'fr_arm_jp2'},
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':2, 'scale':1, 'offset':0, 'name':'fr_arm_jp3'},
+ {'range':(-3.1, 0.0), 'noise':0.05, 'hdr_id':3, 'scale':1, 'offset':0, 'name':'fr_arm_jp4'},
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':4, 'scale':1, 'offset':0, 'name':'fr_arm_jp5'},
+ {'range':(-1.7, 3.8), 'noise':0.05, 'hdr_id':5, 'scale':1, 'offset':-np.pi/2, 'name':'fr_arm_jp6'},
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':6, 'scale':1, 'offset':-np.pi/4, 'name':'fr_arm_jp7'},
+
+ ],
+
+ 'actuator':[
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':0, 'scale':1, 'offset':0, 'name':'panda0_joint1'},
+ {'pos_range':(-1.8326, 1.8326), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':1, 'scale':1, 'offset':0, 'name':'panda0_joint2'},
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':2, 'scale':1, 'offset':0, 'name':'panda0_joint3'},
+ {'pos_range':(-3.1416, 0.0000), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':3, 'scale':1, 'offset':0, 'name':'panda0_joint4'},
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':4, 'scale':1, 'offset':0, 'name':'panda0_joint5'},
+ {'pos_range':(-1.6600, 2.1817), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':5, 'scale':1, 'offset':np.pi/2, 'name':'panda0_joint6'},
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':6, 'scale':1, 'offset':np.pi/4, 'name':'panda0_joint7'},
+ ]
+ },
+
+ 'robotiq':{
+ 'interface': {'type': 'robotiq', 'ip_address':'172.16.0.3'},
+ 'sensor':[
+ {'range':(0, 0.834), 'noise':0.0, 'hdr_id':0, 'name':'robotiq_2f_85', 'scale':-9.81, 'offset':0.834},
+ ],
+ 'actuator':[
+ {'pos_range':(0, 1), 'vel_range':(-20*np.pi/4, 20*np.pi/4), 'hdr_id':0, 'name':'robotiq_2f_85', 'scale':-0.085, 'offset':0.085},
+ ]
+ },
+
+ 'right_cam':{
+ 'interface': {'type': 'realsense',
+ 'rgb_topic':'realsense_817612071438/color/image_raw',
+ 'd_topic': 'realsense_817612071438/depth_uncolored/image_raw',
+ 'data_type':'rgbd'},
+ 'sensor':[],
+ 'cams': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_raw'},
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'d', 'scale':0.05, 'offset':0, 'name':'/depth_mono/image_raw'},
+ ],
+ 'actuator':[]
+ },
+
+ 'left_cam':{
+ 'interface': {'type': 'realsense',
+ 'rgb_topic':'realsense_923322071682/color/image_raw',
+ 'd_topic':'realsense_923322071682/depth_uncolored/image_raw',
+ 'data_type':'rgbd'},
+ 'sensor':[],
+ 'cams': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_raw'},
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'d', 'scale':0.05, 'offset':0, 'name':'/depth_mono/image_raw'},
+ ],
+ 'actuator':[]
+ },
+
+ 'top_cam':{
+ 'interface': {'type': 'realsense',
+ 'rgb_topic':'realsense_831612071935/color/image_raw',
+ 'd_topic': 'realsense_831612071935/depth_uncolored/image_raw',
+ 'data_type':'rgbd'},
+ 'sensor':[],
+ 'cams': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_color'},
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'d', 'scale':0.05, 'offset':0, 'name':'/depth_mono/image_raw'},
+ ],
+ 'actuator':[]
+ },
+
+ 'Franka_wrist_cam':{
+ 'interface': {'type': 'realsense',
+ 'rgb_topic':'realsense_936322070059/color/image_raw',
+ 'd_topic': 'realsense_936322070059/depth_uncolored/image_raw',
+ 'data_type':'rgbd'},
+ 'sensor':[],
+ 'cams': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_color'},
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'d', 'scale':0.05, 'offset':0, 'name':'/depth_mono/image_raw'},
+ ],
+ 'actuator':[]
+ },
+
+}
diff --git a/robohive/envs/arms/franka/assets/franka_hang_push_v0.xml b/robohive/envs/arms/franka/assets/franka_hang_push_v0.xml
new file mode 100644
index 00000000..22b0957b
--- /dev/null
+++ b/robohive/envs/arms/franka/assets/franka_hang_push_v0.xml
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/robohive/envs/arms/franka/assets/franka_planar_push_rp03_v0.config b/robohive/envs/arms/franka/assets/franka_planar_push_rp03_v0.config
new file mode 100644
index 00000000..107398b8
--- /dev/null
+++ b/robohive/envs/arms/franka/assets/franka_planar_push_rp03_v0.config
@@ -0,0 +1,89 @@
+{
+ # device1: sensors, actuators
+ 'franka':{
+ 'interface': {'type': 'franka', 'ip_address':'172.16.0.1', 'gain_scale': 1.0},
+ 'sensor':[
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':0, 'scale':1, 'offset':0, 'name':'fr_arm_jp1'},
+ {'range':(-1.8, 1.8), 'noise':0.05, 'hdr_id':1, 'scale':1, 'offset':0, 'name':'fr_arm_jp2'},
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':2, 'scale':1, 'offset':0, 'name':'fr_arm_jp3'},
+ {'range':(-3.1, 0.0), 'noise':0.05, 'hdr_id':3, 'scale':1, 'offset':0, 'name':'fr_arm_jp4'},
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':4, 'scale':1, 'offset':0, 'name':'fr_arm_jp5'},
+ {'range':(-1.7, 3.8), 'noise':0.05, 'hdr_id':5, 'scale':1, 'offset':-np.pi/2, 'name':'fr_arm_jp6'},
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':6, 'scale':1, 'offset':-np.pi/4, 'name':'fr_arm_jp7'},
+
+ ],
+
+ 'actuator':[
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':0, 'scale':1, 'offset':0, 'name':'panda0_joint1'},
+ {'pos_range':(-1.8326, 1.8326), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':1, 'scale':1, 'offset':0, 'name':'panda0_joint2'},
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':2, 'scale':1, 'offset':0, 'name':'panda0_joint3'},
+ {'pos_range':(-3.1416, 0.0000), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':3, 'scale':1, 'offset':0, 'name':'panda0_joint4'},
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':4, 'scale':1, 'offset':0, 'name':'panda0_joint5'},
+ {'pos_range':(-1.6600, 2.1817), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':5, 'scale':1, 'offset':np.pi/2, 'name':'panda0_joint6'},
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':6, 'scale':1, 'offset':np.pi/4, 'name':'panda0_joint7'},
+ ]
+ },
+
+ # device1: sensors, actuators
+ 'robotiq':{
+ 'interface': {'type': 'robotiq', 'ip_address':'172.16.0.3'},
+ 'sensor':[
+ {'range':(0, 0.834), 'noise':0.0, 'hdr_id':0, 'name':'robotiq_2f_85', 'scale':-9.81, 'offset':0.834},
+ ],
+ 'actuator':[
+ {'pos_range':(0, 1), 'vel_range':(-20*np.pi/4, 20*np.pi/4), 'hdr_id':0, 'name':'robotiq_2f_85', 'scale':-0.085, 'offset':0.085},
+ ]
+ },
+
+ 'right_cam':{
+ 'interface': {'type': 'realsense',
+ 'rgb_topic':'realsense_831612072257/color/image_raw',
+ 'd_topic': 'realsense_831612072257/depth_uncolored/image_raw',
+ 'data_type':'rgbd'},
+ 'sensor':[],
+ 'cam': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_raw'},
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'d', 'scale':0.05, 'offset':0, 'name':'/depth_mono/image_raw'},
+ ],
+ 'actuator':[]
+ },
+
+ 'left_cam':{
+ 'interface': {'type': 'realsense',
+ 'rgb_topic':'realsense_815412070729/color/image_raw',
+ 'd_topic':'realsense_815412070729/depth_uncolored/image_raw',
+ 'data_type':'rgbd'},
+ 'sensor':[],
+ 'cam': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_raw'},
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'d', 'scale':0.05, 'offset':0, 'name':'/depth_mono/image_raw'},
+ ],
+ 'actuator':[]
+ },
+
+ 'top_cam':{
+ 'interface': {'type': 'realsense',
+ 'rgb_topic':'realsense_831612071119/color/image_raw',
+ 'd_topic': 'realsense_831612071119/depth_uncolored/image_raw',
+ 'data_type':'rgbd'},
+ 'sensor':[],
+ 'cam': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_color'},
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'d', 'scale':0.05, 'offset':0, 'name':'/depth_mono/image_raw'},
+ ],
+ 'actuator':[]
+ },
+
+ 'Franka_wrist_cam':{
+ 'interface': {'type': 'realsense',
+ 'rgb_topic':'realsense_814412072030/color/image_raw',
+ 'd_topic': 'realsense_814412072030/depth_uncolored/image_raw',
+ 'data_type':'rgbd'},
+ 'sensor':[],
+ 'cam': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_color'},
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'d', 'scale':0.05, 'offset':0, 'name':'/depth_mono/image_raw'},
+ ],
+ 'actuator':[]
+ },
+}
diff --git a/robohive/envs/arms/franka/assets/franka_planar_push_teleop_v0.xml b/robohive/envs/arms/franka/assets/franka_planar_push_teleop_v0.xml
new file mode 100644
index 00000000..08d3b380
--- /dev/null
+++ b/robohive/envs/arms/franka/assets/franka_planar_push_teleop_v0.xml
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/robohive/envs/arms/franka/assets/franka_planar_push_v0.config b/robohive/envs/arms/franka/assets/franka_planar_push_v0.config
new file mode 100644
index 00000000..2e20a027
--- /dev/null
+++ b/robohive/envs/arms/franka/assets/franka_planar_push_v0.config
@@ -0,0 +1,76 @@
+{
+ # device1: sensors, actuators
+ 'franka':{
+ 'interface': {'type': 'franka', 'ip_address':'172.16.0.1', 'gain_scale': 1.0},
+ 'sensor':[
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':0, 'scale':1, 'offset':0, 'name':'fr_arm_jp1'},
+ {'range':(-1.8, 1.8), 'noise':0.05, 'hdr_id':1, 'scale':1, 'offset':0, 'name':'fr_arm_jp2'},
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':2, 'scale':1, 'offset':0, 'name':'fr_arm_jp3'},
+ {'range':(-3.1, 0.0), 'noise':0.05, 'hdr_id':3, 'scale':1, 'offset':0, 'name':'fr_arm_jp4'},
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':4, 'scale':1, 'offset':0, 'name':'fr_arm_jp5'},
+ {'range':(-1.7, 3.8), 'noise':0.05, 'hdr_id':5, 'scale':1, 'offset':-np.pi/2, 'name':'fr_arm_jp6'},
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':6, 'scale':1, 'offset':-np.pi/4, 'name':'fr_arm_jp7'},
+ ],
+
+ 'actuator':[
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':0, 'scale':1, 'offset':0, 'name':'panda0_joint1'},
+ {'pos_range':(-1.8326, 1.8326), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':1, 'scale':1, 'offset':0, 'name':'panda0_joint2'},
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':2, 'scale':1, 'offset':0, 'name':'panda0_joint3'},
+ {'pos_range':(-3.1416, 0.0000), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':3, 'scale':1, 'offset':0, 'name':'panda0_joint4'},
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':4, 'scale':1, 'offset':0, 'name':'panda0_joint5'},
+ {'pos_range':(-1.6600, 2.1817), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':5, 'scale':1, 'offset':np.pi/2, 'name':'panda0_joint6'},
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':6, 'scale':1, 'offset':np.pi/4, 'name':'panda0_joint7'},
+ ]
+ },
+
+ # device1: sensors, actuators
+ 'robotiq':{
+ 'interface': {'type': 'robotiq', 'ip_address':'172.16.0.8'},
+ 'sensor':[
+ {'range':(0, 0.834), 'noise':0.0, 'hdr_id':0, 'name':'robotiq_2f_85', 'scale':-9.81, 'offset':0.834},
+ ],
+ 'actuator':[
+ {'pos_range':(0, 1), 'vel_range':(-20*np.pi/4, 20*np.pi/4), 'hdr_id':0, 'name':'robotiq_2f_85', 'scale':-0.085, 'offset':0.085},
+ ]
+ },
+
+ 'right_cam':{
+ 'interface': {'type': 'realsense', 'rgb_topic':'realsense_138422075994/color/image_raw', 'd_topic':'realsense_138422075994/depth_uncolored/image_raw'},
+ 'sensor':[],
+ 'cam': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_raw'},
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'d', 'scale':0.05, 'offset':0, 'name':'/depth_mono/image_raw'},
+ ],
+ 'actuator':[]
+ },
+
+ 'left_cam':{
+ 'interface': {'type': 'realsense', 'rgb_topic':'realsense_815412070347/color/image_raw', 'd_topic':'realsense_815412070347/depth_uncolored/image_raw'},
+ 'sensor':[],
+ 'cam': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_raw'},
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'d', 'scale':0.05, 'offset':0, 'name':'/depth_mono/image_raw'},
+ ],
+ 'actuator':[]
+ },
+
+ 'top_cam':{
+ 'interface': {'type': 'realsense', 'rgb_topic':'realsense_815412070804/color/image_raw', 'd_topic':'realsense_815412070804/depth_uncolored/image_raw'},
+ 'sensor':[],
+ 'cam': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_raw'},
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'d', 'scale':0.05, 'offset':0, 'name':'/depth_mono/image_raw'},
+ ],
+ 'actuator':[]
+ },
+
+ 'Franka_wrist_cam':{
+ 'interface': {'type': 'realsense', 'rgb_topic':'realsense_827112071730/color/image_raw', 'd_topic':'realsense_827112071730/depth_uncolored/image_raw'},
+ 'sensor':[],
+ 'cam': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_raw'},
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'d', 'scale':0.05, 'offset':0, 'name':'/depth_mono/image_raw'},
+ ],
+ 'actuator':[]
+ },
+}
\ No newline at end of file
diff --git a/robohive/envs/arms/franka/assets/franka_planar_push_v0.xml b/robohive/envs/arms/franka/assets/franka_planar_push_v0.xml
new file mode 100644
index 00000000..c820ac26
--- /dev/null
+++ b/robohive/envs/arms/franka/assets/franka_planar_push_v0.xml
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/robohive/envs/arms/franka/assets/franka_ycb_v0.config b/robohive/envs/arms/franka/assets/franka_ycb_v0.config
index 54b23efe..3bea08bc 100644
--- a/robohive/envs/arms/franka/assets/franka_ycb_v0.config
+++ b/robohive/envs/arms/franka/assets/franka_ycb_v0.config
@@ -1,7 +1,7 @@
{
# device1: sensors, actuators
'franka':{
- 'interface': {'type': 'franka', 'ip_address':'169.254.163.91'},
+ 'interface': {'type': 'franka', 'ip_address':'172.16.0.1', 'gain_scale': 1.5},
'sensor':[
{'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':0, 'scale':1, 'offset':0, 'name':'fr_arm_jp1'},
{'range':(-1.8, 1.8), 'noise':0.05, 'hdr_id':1, 'scale':1, 'offset':0, 'name':'fr_arm_jp2'},
@@ -10,18 +10,7 @@
{'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':4, 'scale':1, 'offset':0, 'name':'fr_arm_jp5'},
{'range':(-1.7, 3.8), 'noise':0.05, 'hdr_id':5, 'scale':1, 'offset':-np.pi/2, 'name':'fr_arm_jp6'},
{'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':6, 'scale':1, 'offset':-np.pi/4, 'name':'fr_arm_jp7'},
- {'range':(0.00, .04), 'noise':0.05, 'hdr_id':7, 'scale':1, 'offset':0, 'name':'fr_fin_jp1'},
- {'range':(0.00, .04), 'noise':0.05, 'hdr_id':8, 'scale':1, 'offset':0, 'name':'fr_fin_jp2'},
-
- # {'range':(-2*np.pi, np.pi), 'noise':0.05, 'hdr_id':-1, 'scale':1, 'offset':0, 'name':'fr_arm_jv1'},
- # {'range':(-2*np.pi, np.pi), 'noise':0.05, 'hdr_id':-1, 'scale':1, 'offset':0, 'name':'fr_arm_jv2'},
- # {'range':(-2*np.pi, np.pi), 'noise':0.05, 'hdr_id':-1, 'scale':1, 'offset':0, 'name':'fr_arm_jv3'},
- # {'range':(-2*np.pi, np.pi), 'noise':0.05, 'hdr_id':-1, 'scale':1, 'offset':0, 'name':'fr_arm_jv4'},
- # {'range':(-2*np.pi, np.pi), 'noise':0.05, 'hdr_id':-1, 'scale':1, 'offset':0, 'name':'fr_arm_jv5'},
- # {'range':(-2*np.pi, np.pi), 'noise':0.05, 'hdr_id':-1, 'scale':1, 'offset':0, 'name':'fr_arm_jv6'},
- # {'range':(-2*np.pi, np.pi), 'noise':0.05, 'hdr_id':-1, 'scale':1, 'offset':0, 'name':'fr_arm_jv7'},
- # {'range':(-2*np.pi, np.pi), 'noise':0.05, 'hdr_id':-1, 'scale':1, 'offset':0, 'name':'fr_fin_jv1'},
- # {'range':(-2*np.pi, np.pi), 'noise':0.05, 'hdr_id':-1, 'scale':1, 'offset':0, 'name':'fr_fin_jv2'},
+
],
'actuator':[
@@ -32,20 +21,55 @@
{'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':4, 'scale':1, 'offset':0, 'name':'panda0_joint5'},
{'pos_range':(-1.6600, 2.1817), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':5, 'scale':1, 'offset':np.pi/2, 'name':'panda0_joint6'},
{'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':6, 'scale':1, 'offset':np.pi/4, 'name':'panda0_joint7'},
- {'pos_range':(-0.0000, 0.0400), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':-1, 'scale':1, 'offset':0, 'name':'r_gripper_finger_joint'},
- {'pos_range':(-0.0000, 0.0400), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':-1, 'scale':1, 'offset':0, 'name':'l_gripper_finger_joint'},
]
},
- 'object':{
- 'interface':{},
+
+ # device1: sensors, actuators
+ 'robotiq':{
+ 'interface': {'type': 'robotiq', 'ip_address':'172.16.0.3'},
'sensor':[
- {'range':(-1.0, 1.0), 'noise':0.005, 'hdr_id':0, 'scale':1, 'offset':0, 'name':'Tx'},
- {'range':(-0.5, 0.5), 'noise':0.005, 'hdr_id':0, 'scale':1, 'offset':0, 'name':'Ty'},
- {'range':(-1.0, 1.0), 'noise':0.005, 'hdr_id':0, 'scale':1, 'offset':0, 'name':'Tz'},
- {'range':(-3.1, 3.1), 'noise':0.005, 'hdr_id':0, 'scale':1, 'offset':0, 'name':'Rx'},
- {'range':(-3.1, 3.1), 'noise':0.005, 'hdr_id':0, 'scale':1, 'offset':0, 'name':'Ry'},
- {'range':(-3.1, 3.1), 'noise':0.005, 'hdr_id':0, 'scale':1, 'offset':0, 'name':'Rz'},
+ {'range':(0, 0.834), 'noise':0.0, 'hdr_id':0, 'name':'robotiq_2f_85', 'scale':-9.81, 'offset':0.834},
+ ],
+ 'actuator':[
+ {'pos_range':(0, 1), 'vel_range':(-20*np.pi/4, 20*np.pi/4), 'hdr_id':0, 'name':'robotiq_2f_85', 'scale':-0.085, 'offset':0.085},
+ ]
+ },
+
+ 'right_cam':{
+ 'interface': {'type': 'realsense', 'rgb_topic':'realsense_817612071438/color/image_raw', 'd_topic':'realsense_817612071438/depth_uncolored/image_raw'},
+ 'sensor':[],
+ 'cam': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_raw'},
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'d', 'scale':1, 'offset':0, 'name':'/depth_uncolored/image_raw'},
+ ],
+ 'actuator':[]
+ },
+
+ 'left_cam':{
+ 'interface': {'type': 'realsense', 'rgb_topic':'realsense_923322071682/color/image_raw', 'd_topic':'realsense_923322071682/depth_uncolored/image_raw'},
+ 'sensor':[],
+ 'cam': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_raw'},
+ ],
+ 'actuator':[]
+ },
+
+ 'top_cam':{
+ 'interface': {'type': 'realsense', 'rgb_topic':'realsense_831612071935/color/image_raw', 'd_topic':'realsense_831612071935/depth_uncolored/image_raw'},
+ 'sensor':[],
+ 'cam': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_raw'},
],
'actuator':[]
- }
+ },
+
+ 'Franka_wrist_cam':{
+ 'interface': {'type': 'realsense', 'rgb_topic':'realsense_936322070059/color/image_raw', 'd_topic':'realsense_936322070059/depth_uncolored/image_raw'},
+ 'sensor':[],
+ 'cam': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_raw'},
+ ],
+ 'actuator':[]
+ },
+
}
\ No newline at end of file
diff --git a/robohive/envs/arms/franka/assets/franka_ycb_v0.xml b/robohive/envs/arms/franka/assets/franka_ycb_v0.xml
index d18ca51a..81096ccb 100644
--- a/robohive/envs/arms/franka/assets/franka_ycb_v0.xml
+++ b/robohive/envs/arms/franka/assets/franka_ycb_v0.xml
@@ -10,40 +10,47 @@
+
-
-
-
+
+
-
-
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
-
+
+
+
-
+
@@ -65,4 +72,4 @@
-
\ No newline at end of file
+
diff --git a/robohive/envs/arms/push_base_v0.py b/robohive/envs/arms/push_base_v0.py
index 56f9985b..43966785 100644
--- a/robohive/envs/arms/push_base_v0.py
+++ b/robohive/envs/arms/push_base_v0.py
@@ -5,26 +5,65 @@
License :: Under Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
================================================= """
+import os
import collections
import gym
import numpy as np
from robohive.envs import env_base
+from robohive.physics.sim_scene import SimScene
+from robohive.utils.xml_utils import reassign_parent
+from robohive.utils.quat_math import mat2euler, euler2quat, mat2quat
+from robohive.utils.inverse_kinematics import qpos_from_site_pose
class PushBaseV0(env_base.MujocoEnv):
DEFAULT_OBS_KEYS = [
- 'qp', 'qv', 'object_err', 'target_err'
+ 'qp', 'qv', 'grasp_pos', 'grasp_rot', 'object_err', 'target_err'
]
DEFAULT_RWD_KEYS_AND_WEIGHTS = {
"object_dist": -1.0,
- "target_dist": -1.0,
+ "target_dist": -5.0,
"bonus": 4.0,
"penalty": -50,
}
def __init__(self, model_path, obsd_model_path=None, seed=None, **kwargs):
+ # Process model to use Robotiq/DManus as end effector
+ raw_sim = SimScene.get_sim(model_path)
+ raw_xml = raw_sim.model.get_xml()
+ processed_xml = reassign_parent(xml_str=raw_xml, receiver_node="panda0_link7", donor_node="ee_mount")
+ processed_model_path = model_path[:-4]+"_processed.xml"
+
+ cur_xml = None
+ if os.path.exists(processed_model_path):
+ with open(processed_model_path,'r') as file:
+ cur_xml = file.read()
+
+ if cur_xml != processed_xml:
+ with open(processed_model_path, 'w') as file:
+ file.write(processed_xml)
+
+ # Process model to use DManus as end effector
+ if obsd_model_path == model_path:
+ processed_obsd_model_path = processed_model_path
+ elif obsd_model_path:
+ raw_sim = SimScene.get_sim(obsd_model_path)
+ raw_xml = raw_sim.model.get_xml()
+ processed_xml = reassign_parent(xml_str=raw_xml, receiver_node="panda0_link7", donor_node="ee_mount")
+ processed_obsd_model_path = obsd_model_path[:-4]+"_processed.xml"
+
+ cur_xml = None
+ if os.path.exists(processed_obsd_model_path):
+ with open(processed_obsd_model_path,'r') as file:
+ cur_xml = file.read()
+ if cur_xml != processed_xml:
+ with open(processed_obsd_model_path, 'w') as file:
+ file.write(processed_xml)
+ else:
+ processed_obsd_model_path = None
+
# EzPickle.__init__(**locals()) is capturing the input dictionary of the init method of this class.
# In order to successfully capture all arguments we need to call gym.utils.EzPickle.__init__(**locals())
# at the leaf level, when we do inheritance like we do here.
@@ -37,16 +76,22 @@ def __init__(self, model_path, obsd_model_path=None, seed=None, **kwargs):
# first construct the inheritance chain, which is just __init__ calls all the way down, with env_base
# creating the sim / sim_obsd instances. Next we run through "setup" which relies on sim / sim_obsd
# created in __init__ to complete the setup.
- super().__init__(model_path=model_path, obsd_model_path=obsd_model_path, seed=seed)
+ super().__init__(model_path=processed_model_path, obsd_model_path=processed_obsd_model_path, seed=seed)
- self._setup(**kwargs)
+ self._setup(processed_model_path, **kwargs)
def _setup(self,
+ model_path,
robot_site_name,
object_site_name,
target_site_name,
target_xyz_range,
+ init_qpos=None,
+ pos_limits=None,
+ vel_limits=None,
+ obj_pos_limits=None,
+ max_ik=3,
frame_skip=40,
reward_mode="dense",
obs_keys=DEFAULT_OBS_KEYS,
@@ -56,21 +101,56 @@ def _setup(self,
# ids
self.grasp_sid = self.sim.model.site_name2id(robot_site_name)
+ self.object_site_name = object_site_name
self.object_sid = self.sim.model.site_name2id(object_site_name)
self.target_sid = self.sim.model.site_name2id(target_site_name)
self.target_xyz_range = target_xyz_range
+ self.pos_limits = pos_limits
+ self.vel_limits = vel_limits
+ self.obj_pos_limits = obj_pos_limits
+ self.max_ik = max_ik
+
+ self.ik_sim = SimScene.get_sim(model_path)
+ self.last_eef_cmd = None
+
+ assert(self.pos_limits is None or
+ ('eef_high' in self.pos_limits and 'eef_low' in self.pos_limits ))
+ assert(self.vel_limits is None or
+ ('jnt' in self.vel_limits and 'eef' in self.vel_limits))
+ assert(self.obj_pos_limits is None or
+ ('low' in self.obj_pos_limits and 'high' in self.obj_pos_limits))
+
+ if pos_limits is not None:
+ for key in pos_limits.keys():
+ pos_limits[key] = np.array(pos_limits[key])
+ if vel_limits is not None:
+ for key in vel_limits.keys():
+ vel_limits[key] = np.array(vel_limits[key])
+ if obj_pos_limits is not None:
+ for key in obj_pos_limits.keys():
+ obj_pos_limits[key] = np.array(obj_pos_limits[key])
+
super()._setup(obs_keys=obs_keys,
weighted_reward_keys=weighted_reward_keys,
reward_mode=reward_mode,
frame_skip=frame_skip,
**kwargs)
+ if init_qpos is not None:
+ self.init_qpos[:len(init_qpos)] = np.array(init_qpos)[:]
+
+ if self.pos_limits is not None:
+ act_low = -np.ones(self.pos_limits['eef_low'].shape[0]) if self.normalize_act else self.pos_limits['eef_low'].copy()
+ act_high = np.ones(self.pos_limits['eef_high'].shape[0]) if self.normalize_act else self.pos_limits['eef_high'].copy()
+ self.action_space = gym.spaces.Box(act_low, act_high, dtype=np.float32)
def get_obs_dict(self, sim):
obs_dict = {}
obs_dict['time'] = np.array([self.sim.data.time])
obs_dict['qp'] = sim.data.qpos.copy()
obs_dict['qv'] = sim.data.qvel.copy()
+ obs_dict['grasp_pos'] = sim.data.site_xpos[self.grasp_sid].copy()
+ obs_dict['grasp_rot'] = mat2quat(self.sim.data.site_xmat[self.grasp_sid].reshape(3,3).transpose())
obs_dict['object_err'] = sim.data.site_xpos[self.object_sid]-sim.data.site_xpos[self.grasp_sid]
obs_dict['target_err'] = sim.data.site_xpos[self.target_sid]-sim.data.site_xpos[self.object_sid]
return obs_dict
@@ -88,15 +168,129 @@ def get_reward_dict(self, obs_dict):
('bonus', (object_dist<.1) + (target_dist<.1) + (target_dist<.05)),
('penalty', (object_dist>far_th)),
# Must keys
- ('sparse', -1.0*target_dist),
+ ('sparse', -1.0*(target_dist<.050)),
('solved', target_dist<.050),
('done', object_dist > far_th),
))
rwd_dict['dense'] = np.sum([wt*rwd_dict[key] for key, wt in self.rwd_keys_wt.items()], axis=0)
return rwd_dict
- def reset(self):
+ def reset(self, reset_qpos=None, reset_qvel=None, **kwargs):
self.sim.model.site_pos[self.target_sid] = self.np_random.uniform(high=self.target_xyz_range['high'], low=self.target_xyz_range['low'])
self.sim_obsd.model.site_pos[self.target_sid] = self.sim.model.site_pos[self.target_sid]
- obs = super().reset(self.init_qpos, self.init_qvel)
+
+ if reset_qpos is None:
+ reset_qpos = self.init_qpos.copy()
+ if self.obj_pos_limits is not None:
+ obj_jid = self.sim.model.joint_name2id(self.object_site_name)
+ reset_qpos[obj_jid:obj_jid+3] = self.np_random.uniform(low=self.obj_pos_limits['low'], high=self.obj_pos_limits['high'])
+
+ obs = super().reset(reset_qpos, reset_qvel, blocking=False, **kwargs)
+
+ cur_pos = self.sim.data.site_xpos[self.grasp_sid]
+ cur_rot = mat2euler(self.sim.data.site_xmat[self.grasp_sid].reshape(3,3).transpose())
+ if self.pos_limits is not None:
+ cur_rot[cur_rot < self.pos_limits['eef_low'][3:6]] += 2*np.pi
+ cur_rot[cur_rot > self.pos_limits['eef_high'][3:6]] -= 2 * np.pi
+
+ self.last_eef_cmd = np.concatenate([cur_pos,
+ cur_rot,
+ [self.sim.data.qpos[7]]])
+
return obs
+
+ def get_ik_action(self, eef_pos, eef_quat):
+ for i in range(self.max_ik):
+
+ self.ik_sim.data.qpos[:7] = np.random.normal(self.sim.data.qpos[:7], i*0.1)
+
+ self.ik_sim.data.qpos[2] = 0.0
+ self.ik_sim.forward()
+
+ ik_result = qpos_from_site_pose(physics = self.ik_sim,
+ site_name = self.sim.model.site_id2name(self.grasp_sid),
+ target_pos= eef_pos,
+ target_quat= eef_quat,
+ inplace=False,
+ regularization_strength=1.0)
+
+ if ik_result.success:
+ break
+ return ik_result
+
+ def step(self, a, **kwargs):
+ assert(len(a.shape) == 1)
+ assert(a.shape[0] == self.sim.model.nu or a.shape[0] == 7)
+
+ jnt_act_low = self.sim.model.actuator_ctrlrange[:,0].copy()
+ jnt_act_high = self.sim.model.actuator_ctrlrange[:,1].copy()
+
+ if a.shape[0] == self.sim.model.nu:
+ action = a
+ if self.normalize_act:
+ action = (0.5 * action + 0.5) * (jnt_act_high - jnt_act_low) + jnt_act_low
+
+ else:
+ # Un-normalize cmd
+ eef_cmd = a
+ if self.normalize_act:
+ eef_cmd = (0.5 * eef_cmd + 0.5) * (self.pos_limits['eef_high'] - self.pos_limits['eef_low']) + \
+ self.pos_limits['eef_low']
+
+ if self.pos_limits is not None:
+ eef_cmd = np.clip(eef_cmd,
+ self.pos_limits['eef_low'],
+ self.pos_limits['eef_high'])
+
+ # Get current position and rotation of eef
+ cur_pose = self.sim.data.site_xpos[self.grasp_sid]
+
+ # Enforce cartesian velocity limits
+ if self.vel_limits is not None:
+ eef_cmd[:3] = np.clip(eef_cmd[:3],
+ cur_pose - self.vel_limits['eef'],
+ cur_pose + self.vel_limits['eef'])
+
+ # Exponential moving average to limit jerk
+ assert self.last_eef_cmd is not None
+ eef_cmd[:3] = 0.25 * eef_cmd[:3] + 0.75 * self.last_eef_cmd[:3]
+
+ # Prepare for IK, execute last successful command if IK fails
+ eef_pos = eef_cmd[:3]
+ eef_elr = eef_cmd[3:6]
+ eef_quat = euler2quat(eef_elr)
+
+ ik_result = self.get_ik_action(eef_pos, eef_quat)
+ ik_success = ik_result.success
+ if not ik_success:
+ eef_cmd = self.last_eef_cmd
+ eef_pos = eef_cmd[:3]
+ eef_elr = eef_cmd[3:6]
+ eef_quat = euler2quat(eef_elr)
+ ik_result = self.get_ik_action(eef_pos, eef_quat)
+
+ action = ik_result.qpos[:self.sim.model.nu]
+ action[7:self.sim.model.nu] = eef_cmd[6]
+
+ self.last_eef_cmd = eef_cmd
+
+
+ # Enforce joint position limits
+ action = np.clip(action, jnt_act_low, jnt_act_high)
+
+ # Enforce joint velocity limits
+ if self.vel_limits is not None:
+ action = np.clip(action,
+ self.sim.data.qpos[:self.sim.model.nu] - self.vel_limits['jnt'],
+ self.sim.data.qpos[:self.sim.model.nu] + self.vel_limits['jnt'])
+
+ if self.normalize_act:
+ action = 2 * (((action - jnt_act_low) / (jnt_act_high - jnt_act_low)) - 0.5)
+
+ self.last_ctrl = self.robot.step(ctrl_desired=action,
+ ctrl_normalized=self.normalize_act,
+ step_duration=self.dt,
+ realTimeSim=self.mujoco_render_frames,
+ render_cbk=self.mj_render if self.mujoco_render_frames else None)
+ return self.forward(**kwargs)
+
diff --git a/robohive/envs/env_base.py b/robohive/envs/env_base.py
index 4d91bfea..6fe46a09 100644
--- a/robohive/envs/env_base.py
+++ b/robohive/envs/env_base.py
@@ -71,6 +71,7 @@ def _setup(self,
obs_range:tuple = (-10, 10), # Permissible range of values in obs vector returned by get_obs()
rwd_viz:bool = False, # Visualize rewards (WIP, needs vtils)
device_id:int = 0, # Device id for rendering
+ torque_scale:float=1.0,
**kwargs, # Additional arguments
):
@@ -136,6 +137,8 @@ def _setup(self,
self.obs_dim = observation.size
self.observation_space = gym.spaces.Box(obs_range[0]*np.ones(self.obs_dim), obs_range[1]*np.ones(self.obs_dim), dtype=np.float32)
+ self.sim.model.actuator_forcerange[:] *= torque_scale
+
return
@@ -341,44 +344,58 @@ def get_visuals(self, sim=None, visual_keys:list=None, device_id:int=None)->dict
# collect visuals
visual_dict = {}
visual_dict['time'] = np.array([self.sim.data.time])
+ cameras = []
+ img_keys = []
+ height = None
+ width = None
for key in visual_keys:
if key.startswith('rgb'):
_, cam, wxh, rgb_encoder_id = key.split(':')
- height = int(wxh.split('x')[0])
- width = int(wxh.split('x')[1])
- # render images ==> returns (ncams, height, width, 3)
- img, dpt = self.robot.get_visual_sensors(
- height=height,
- width=width,
- cameras=[cam],
- device_id=device_id,
- sim=sim,
- )
- # encode images
- if rgb_encoder_id == '1d':
- rgb_encoded = img[0].reshape(-1)
- elif rgb_encoder_id == '2d':
- rgb_encoded = img[0]
- elif rgb_encoder_id[:3] == 'r3m' or rgb_encoder_id[:3] == 'rrl':
- with torch.no_grad():
- rgb_encoded = 255.0 * self.rgb_transform(img[0]).reshape(-1, 3, 224, 224)
- rgb_encoded = rgb_encoded.to(self.device_encoder)
- rgb_encoded = self.rgb_encoder(rgb_encoded).cpu().numpy()
- rgb_encoded = np.squeeze(rgb_encoded)
- elif rgb_encoder_id[:3] == 'vc1':
- with torch.no_grad():
- rgb_encoded = self.rgb_transform(torch.Tensor(img.transpose(0,3,1,2)))
- rgb_encoded = rgb_encoded.to(self.device_encoder)
- rgb_encoded = self.rgb_encoder(rgb_encoded).cpu().numpy()
- rgb_encoded = np.squeeze(rgb_encoded)
+
+ if height is None:
+ height = int(wxh.split('x')[0])
+ width = int(wxh.split('x')[1])
else:
- raise ValueError("Unsupported visual encoder: {}".format(rgb_encoder_id))
+ assert(height == int(wxh.split('x')[0]))
+ assert(width == int(wxh.split('x')[1]))
+ cameras.append(cam)
+ img_keys.append(key)
+
+ if len(cameras) >= 1:
+ # render images ==> returns (ncams, height, width, 3)
+ img, dpt = self.robot.get_visual_sensors(
+ height=height,
+ width=width,
+ cameras=cameras,
+ device_id=device_id,
+ sim=sim,
+ )
+ # encode images
+ if rgb_encoder_id == '1d':
+ rgb_encoded = img.reshape(-1)
+ elif rgb_encoder_id == '2d':
+ rgb_encoded = img
+ elif rgb_encoder_id[:3] == 'r3m' or rgb_encoder_id[:3] == 'rrl':
+ with torch.no_grad():
+ rgb_encoded = 255.0 * self.rgb_transform(img).reshape(-1, 3, 224, 224)
+ rgb_encoded = rgb_encoded.to(self.device_encoder)
+ rgb_encoded = self.rgb_encoder(rgb_encoded).cpu().numpy()
+ rgb_encoded = np.squeeze(rgb_encoded)
+ elif rgb_encoder_id[:3] == 'vc1':
+ with torch.no_grad():
+ rgb_encoded = self.rgb_transform(torch.Tensor(img.transpose(0,3,1,2)))
+ rgb_encoded = rgb_encoded.to(self.device_encoder)
+ rgb_encoded = self.rgb_encoder(rgb_encoded).cpu().numpy()
+ rgb_encoded = np.squeeze(rgb_encoded)
+ else:
+ raise ValueError("Unsupported visual encoder: {}".format(rgb_encoder_id))
- visual_dict.update({key:rgb_encoded})
+ for key_idx, key in enumerate(img_keys):
+ visual_dict.update({key:rgb_encoded[key_idx]})
# add depth observations if requested in the keys (assumption d will always be accompanied by rgb keys)
d_key = 'd:'+key[4:]
- if d_key in self.obs_keys:
- visual_dict.update({d_key:dpt})
+ if d_key in self.visual_keys:
+ visual_dict.update({d_key:np.expand_dims(dpt[key_idx],axis=0)})
return visual_dict
@@ -593,9 +610,17 @@ def evaluate_success(self, paths, logger=None, successful_steps=5):
num_paths = len(paths)
# Record success if solved for provided successful_steps
- for path in paths:
- if np.sum(path['env_infos']['solved'] * 1.0) > successful_steps:
+ for i, path in enumerate(paths):
+ if 'env_infos' in path:
+ success = np.sum(path['env_infos']['solved'] * 1.0) > successful_steps
+ elif 'env_infos' in path['Trial'+str(i)]:
+ success = np.sum([ _data['solved']*1.0 for _data in path['Trial'+str(i)]['env_infos']]) > successful_steps
# sum of truth values may not work correctly if dtype=object, need to * 1.0
+ elif 'env_infos/solved' in path['Trial'+str(i)]:
+ success = np.sum(path['Trial'+str(i)]['env_infos/solved'] * 1.0) > successful_steps
+ else:
+ raise NotImplementedError()
+ if success:
num_success += 1
success_percentage = num_success*100.0/num_paths
diff --git a/robohive/envs/fm/__init__.py b/robohive/envs/fm/__init__.py
index 16dd0562..43a555b3 100644
--- a/robohive/envs/fm/__init__.py
+++ b/robohive/envs/fm/__init__.py
@@ -90,4 +90,31 @@
"d:Franka_wrist_cam:{}:{}".format(img_res, encoder_type),
]
}
+)
+
+encoder_type = "2d"
+# img_res="480x640"
+img_res="240x424"
+register(
+ id='rpFrankaRobotiqData_rp08-v0',
+ entry_point='robohive.envs.fm.franka_robotiq_data_v0:FrankaRobotiqData',
+ max_episode_steps=50, #50steps*40Skip*2ms = 4s
+ kwargs={
+ 'model_path': '/assets/franka_robotiq.xml',
+ 'config_path': curr_dir+'/assets/franka_robotiq_rp08.config',
+ 'nq_arm':7,
+ 'nq_ee':1,
+ 'name_ee':'end_effector',
+ 'visual_keys':[
+ # customize the visual keys
+ "rgb:left_cam:{}:{}".format(img_res, encoder_type),
+ "rgb:right_cam:{}:{}".format(img_res, encoder_type),
+ "rgb:top_cam:{}:{}".format(img_res, encoder_type),
+ "rgb:Franka_wrist_cam:{}:{}".format(img_res, encoder_type),
+ "d:left_cam:{}:{}".format(img_res, encoder_type),
+ "d:right_cam:{}:{}".format(img_res, encoder_type),
+ "d:top_cam:{}:{}".format(img_res, encoder_type),
+ "d:Franka_wrist_cam:{}:{}".format(img_res, encoder_type),
+ ]
+ }
)
\ No newline at end of file
diff --git a/robohive/envs/fm/assets/franka_robotiq.xml b/robohive/envs/fm/assets/franka_robotiq.xml
index 42bc326f..b9bf7580 100644
--- a/robohive/envs/fm/assets/franka_robotiq.xml
+++ b/robohive/envs/fm/assets/franka_robotiq.xml
@@ -9,14 +9,14 @@
-
-
-
-
-
-
+
+
+
+
+
+
-
+
@@ -28,20 +28,20 @@
-
+
-
+
-
+
-
+
diff --git a/robohive/envs/fm/assets/franka_robotiq_rp08.config b/robohive/envs/fm/assets/franka_robotiq_rp08.config
new file mode 100644
index 00000000..8db2216c
--- /dev/null
+++ b/robohive/envs/fm/assets/franka_robotiq_rp08.config
@@ -0,0 +1,74 @@
+{
+
+ # device1: sensors, actuators
+ 'franka':{
+ 'interface': {'type': 'franka', 'ip_address':'172.16.0.1', 'gain_scale':0.5},
+ 'sensor':[
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':0, 'scale':1, 'offset':0, 'name':'fr_arm_jp1'},
+ {'range':(-1.8, 1.8), 'noise':0.05, 'hdr_id':1, 'scale':1, 'offset':0, 'name':'fr_arm_jp2'},
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':2, 'scale':1, 'offset':0, 'name':'fr_arm_jp3'},
+ {'range':(-3.1, 0.0), 'noise':0.05, 'hdr_id':3, 'scale':1, 'offset':0, 'name':'fr_arm_jp4'},
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':4, 'scale':1, 'offset':0, 'name':'fr_arm_jp5'},
+ {'range':(-1.7, 3.8), 'noise':0.05, 'hdr_id':5, 'scale':1, 'offset':-np.pi/2, 'name':'fr_arm_jp6'},
+ {'range':(-2.9, 2.9), 'noise':0.05, 'hdr_id':6, 'scale':1, 'offset':-np.pi/4, 'name':'fr_arm_jp7'},
+ ],
+
+ 'actuator':[
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':0, 'scale':1, 'offset':0, 'name':'panda0_joint1'},
+ {'pos_range':(-1.8326, 1.8326), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':1, 'scale':1, 'offset':0, 'name':'panda0_joint2'},
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':2, 'scale':1, 'offset':0, 'name':'panda0_joint3'},
+ {'pos_range':(-3.1416, 0.0000), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':3, 'scale':1, 'offset':0, 'name':'panda0_joint4'},
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':4, 'scale':1, 'offset':0, 'name':'panda0_joint5'},
+ {'pos_range':(-1.6600, 2.1817), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':5, 'scale':1, 'offset':np.pi/2, 'name':'panda0_joint6'},
+ {'pos_range':(-2.9671, 2.9671), 'vel_range':(-4*np.pi/2, 4*np.pi/2), 'hdr_id':6, 'scale':1, 'offset':np.pi/4, 'name':'panda0_joint7'},
+ ]
+ },
+
+ # device1: sensors, actuators
+ 'robotiq':{
+ 'interface': {'type': 'robotiq', 'ip_address':'172.16.0.8'},
+ 'sensor':[
+ {'range':(0, 0.834), 'noise':0.0, 'hdr_id':0, 'name':'robotiq_2f_85', 'scale':-9.81, 'offset':0.834},
+ ],
+ 'actuator':[
+ {'pos_range':(0, 1), 'vel_range':(-20*np.pi/4, 20*np.pi/4), 'hdr_id':0, 'name':'robotiq_2f_85', 'scale':-0.085, 'offset':0.085},
+ ]
+ },
+
+ 'right_cam':{
+ 'interface': {'type': 'realsense', 'rgb_topic':'realsense_138422075994/color/image_raw', 'd_topic':'realsense_138422075994/depth_uncolored/image_raw'},
+ 'sensor':[],
+ 'cam': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_raw'},
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'d', 'scale':1, 'offset':0, 'name':'/depth_uncolored/image_raw'},
+ ],
+ 'actuator':[]
+ },
+
+ 'left_cam':{
+ 'interface': {'type': 'realsense', 'rgb_topic':'realsense_815412070347/color/image_raw', 'd_topic':'realsense_815412070347/depth_uncolored/image_raw'},
+ 'sensor':[],
+ 'cam': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_raw'},
+ ],
+ 'actuator':[]
+ },
+
+ 'top_cam':{
+ 'interface': {'type': 'realsense', 'rgb_topic':'realsense_815412070804/color/image_raw', 'd_topic':'realsense_815412070804/depth_uncolored/image_raw'},
+ 'sensor':[],
+ 'cam': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_raw'},
+ ],
+ 'actuator':[]
+ },
+
+ 'Franka_wrist_cam':{
+ 'interface': {'type': 'realsense', 'rgb_topic':'realsense_827112071730/color/image_raw', 'd_topic':'realsense_827112071730/depth_uncolored/image_raw'},
+ 'sensor':[],
+ 'cam': [
+ {'range':(0, 255), 'noise':0.00, 'hdr_id':'rgb', 'scale':1, 'offset':0, 'name':'/color/image_raw'},
+ ],
+ 'actuator':[]
+ },
+}
\ No newline at end of file
diff --git a/robohive/logger/examine_logs.py b/robohive/logger/examine_logs.py
index ef1387fa..da203bc1 100644
--- a/robohive/logger/examine_logs.py
+++ b/robohive/logger/examine_logs.py
@@ -1,5 +1,5 @@
DESC = '''
-Helper script to record/examine a rollout (record/ render/ playback/ recover) on an environment\n
+Helper script to record/examine a rollout's openloop effects (record/ render/ playback/ recover) on an environment\n
> Examine options:\n
- Record: Record an execution. (Useful for kinesthetic demonstrations on hardware)\n
- Render: Render back the execution. (sim.forward)\n
@@ -8,22 +8,22 @@
> Render options\n
- either onscreen, or offscreen, or just rollout without rendering.\n
> Save options:\n
- - save resulting rollouts as RoboHive/Roboset format, and as 2D plots\n
+ - save resulting paths as RoboHive format, and as 2D plots\n
USAGE:\n
$ python examine_rollout.py --env_name door-v0 \n
$ python examine_rollout.py --env_name door-v0 --rollout_path my_rollouts.h5 --repeat 10 \n
$ python logger/examine_logs.py --env_name rpFrankaRobotiqData-v0 --rollout_path teleOp_trace.h5 --rollout_format RoboSet --render offscreen --compress_paths False -c left_cam -c right_cam -c top_cam -c Franka_wrist_cam --plot_paths True
'''
-from robohive.utils.paths_utils import plot as plotnsave_paths
-from robohive.utils import tensor_utils
import gym
+from robohive.utils.paths_utils import plot as plotnsave_paths
import click
import numpy as np
import time
import os
+from robohive.logger.grouped_datasets import Trace
-
+# python examine_logs.py -e FrankaBinPickReal_v2d-v0 -p /mnt/raid5/data/plancaster/robohive_base/demonstrations/FrankaBinPick_v2d/robopen07_20230403-195410_paths.pickle -r none --env_args {\'is_hardware\':True}
@click.command(help=DESC)
@click.option('-e', '--env_name', type=str, help='environment to load', required=True)
@click.option('-p', '--rollout_path', type=str, help='absolute path of the rollout', default=None)
@@ -50,22 +50,13 @@ def main(env_name, rollout_path, rollout_format, mode, horizon, seed, num_repeat
env = gym.make(env_name) if env_args==None else gym.make(env_name, **(eval(env_args)))
env.seed(seed)
- # Start a "trace" for recording rollouts
- if rollout_format=='RoboHive':
- from robohive.logger.grouped_datasets import Trace
- elif rollout_format=='RoboSet':
- from robohive.logger.roboset_logger import RoboSet_Trace as Trace
- else:
- raise TypeError("unknown rollout_format format")
- trace = Trace("Rollouts")
-
- # Load old traces as "paths"; none if record
+ # Load paths
if mode == 'record':
assert horizon>0, "Rollout horizon must be specified when recording rollout"
assert output_name is not None, "Specify the name of the recording"
if save_paths is False:
print("Warning: Recording is not being saved. Enable save_paths=True to log the recorded path")
- paths = [None,]*num_repeat # Mark old traces as None
+ paths = [None,]*num_repeat # empty paths for recordings
else:
assert rollout_path is not None, "Rollout path is required for mode:{} ".format(mode)
if output_dir == './': # overide the default
@@ -74,7 +65,7 @@ def main(env_name, rollout_path, rollout_format, mode, horizon, seed, num_repeat
rollout_name = os.path.split(rollout_path)[-1]
output_name, output_type = os.path.splitext(rollout_name)
paths = Trace.load(rollout_path)
-
+ paths.close()
# Resolve rendering
if render == 'onscreen':
env.env.mujoco_render_frames = True
@@ -84,6 +75,7 @@ def main(env_name, rollout_path, rollout_format, mode, horizon, seed, num_repeat
env.mujoco_render_frames = False
# Rollout paths
+ trace = Trace("Rollouts Trajectories")
for i_loop in range(num_repeat):
# Rollout path
@@ -97,33 +89,33 @@ def main(env_name, rollout_path, rollout_format, mode, horizon, seed, num_repeat
trace.create_group(path_name)
# init: reset to starting state
- if path_data and rollout_format=='RoboHive':
+ if rollout_format=='RoboHive':
+ path_horizon = path_data['time'].shape[0]-1
# reset to init state
- if "state" in path_data['env_infos'].keys():
- path_state = tensor_utils.split_tensor_dict_list(path_data['env_infos']['state'])
- env.reset(reset_qpos=path_state[0]['qpos'], reset_qvel=path_state[0]['qvel'])
- env.env.set_env_state(path_state[0])
+ print(path_data.keys())
+ if 'env_infos' in path_data and "state" in path_data['env_infos'].keys():
+ state = {}
+ for k in path_data['env_infos']['state'].keys(): state[k] = path_data['env_infos']['state'][k][0]
+ env.reset(reset_qpos=path_data['env_infos']['state']['qpos'][0], reset_qvel=path_data['env_infos']['state']['qvel'][0])
+ env.env.set_env_state(state)
else:
env.reset()
- elif path_data and rollout_format=='RoboSet':
+ elif rollout_format=='RoboSet':
path_data = path_data['data']
+ path_horizon = path_data['ctrl_arm'].shape[0]-1
# reset to init state
reset_qpos = env.init_qpos.copy()
nq_arm = len(path_data['qp_arm'][0])
reset_qpos[:nq_arm] = path_data['qp_arm'][0]
- nq_ee = len(path_data['qp_ee'][0])
- reset_qpos[nq_arm:nq_arm+nq_ee] = path_data['qp_ee'][0]
+ reset_qpos[nq_arm] = path_data['qp_ee'][0] # assumption
env.reset(reset_qpos=reset_qpos)
- elif mode=="record":
- env.reset()
else:
- raise TypeError(f"Unknown rollout_format{rollout_format} / mode:{mode}")
- trace_horizon = horizon if mode=='record' else path_data['time'].shape[0]-1
+ raise TypeError("Unknown rollout_format")
# Rollout path --------------------------------
ep_rwd = 0.0
obs, rwd, done, env_info = env.forward()
- for i_step in range(trace_horizon+1):
+ for i_step in range(path_horizon+1):
# Get step's actions ----------------------
@@ -133,10 +125,19 @@ def main(env_name, rollout_path, rollout_format, mode, horizon, seed, num_repeat
# Directly create the scene
elif mode=='render':
- # populate actions merely for logging
+ env.sim.data.time = path_data['time'][i_step]
if rollout_format=='RoboSet':
+ env.sim.data.qpos[:nq_arm]= path_data['qp_arm'][i_step]
+ env.sim.data.qpos[nq_arm]= path_data['qp_ee'][i_step] # assumption
+ env.sim.data.qve[:nq_arm]= path_data['qv_arm'][i_step]
+ env.sim.data.qvel[nq_arm]= path_data['qv_ee'][i_step] # assumption
+ # populate actions merely for logging
act = np.concatenate([path_data['ctrl_arm'][i_step], path_data['ctrl_ee'][i_step]])
+
elif rollout_format=='RoboHive' and "state" in path_data['env_infos'].keys():
+ env.sim.data.qpos[:]= path_data['env_infos']['state']['qpos'][i_step]
+ env.sim.data.qvel[:]= path_data['env_infos']['state']['qvel'][i_step]
+ # populate actions merely for logging
act = path_data['actions'][i_step]
else:
raise NotImplementedError("Settings not found")
@@ -161,13 +162,13 @@ def main(env_name, rollout_path, rollout_format, mode, horizon, seed, num_repeat
act = env.robot.normalize_actions(controls=act)
# nan actions for last log entry
- if i_step == trace_horizon:
+ if i_step == path_horizon:
act = np.nan*np.ones(env.action_space.shape)
# log values at time=t ----------------------------------
if compress_paths:
obs = [] # don't save obs, env_infos has obs_dict
- if 'state' in env_info.keys(): del env_info['state'] # don't save state, obs_dict has env necessities
+ del env_info['state'] # don't save state, obs_dict has env necessities
# log: time, obs, act, rwd, info, done
datum_dict = dict(
@@ -179,6 +180,7 @@ def main(env_name, rollout_path, rollout_format, mode, horizon, seed, num_repeat
done=done,
)
trace.append_datums(group_key=path_name,dataset_key_val=datum_dict)
+ # print(f't={env.time:2.2}, a={act}, o={obs[:3]}')
# log: offscreen frames
if render =='offscreen':
@@ -193,22 +195,12 @@ def main(env_name, rollout_path, rollout_format, mode, horizon, seed, num_repeat
trace.append_datum(group_key=path_name,dataset_key=cam, dataset_val=curr_frame)
# step/forward env using actions from t=>t+1 ----------------------
- if mode=='render' and i_step < trace_horizon:
- if rollout_format=='RoboSet':
- env.sim.data.qpos[:nq_arm]= path_data['qp_arm'][i_step+1]
- env.sim.data.qpos[nq_arm:nq_arm+nq_ee]= path_data['qp_ee'][i_step+1]
- env.sim.data.qve[:nq_arm]= path_data['qv_arm'][i_step+1]
- env.sim.data.qvel[nq_arm:nq_arm+nq_ee]= path_data['qv_ee'][i_step+1]
- env.sim.data.time = path_data['time'][i_step+1]
- elif rollout_format=='RoboHive' and "state" in path_data['env_infos'].keys():
- env.set_env_state(path_state[i_step+1])
- else:
- raise NotImplementedError("Settings not found")
+ if mode=='render':
+ env.sim.forward()
obs, rwd, done, env_info = env.forward()
- ep_rwd += rwd
- elif i_step < trace_horizon: # incase last step actions (nans) can cause issues in step
+ elif i_step < path_horizon: #incase last step actions (nans) can cause issues in step
obs, rwd, done, env_info = env.step(act)
- ep_rwd += rwd
+ ep_rwd += rwd
# save offscreen buffers as video and clear the dataset
if render == 'offscreen':
@@ -224,7 +216,6 @@ def main(env_name, rollout_path, rollout_format, mode, horizon, seed, num_repeat
# plot paths ???: Needs upgrade to the new logger
trace.stack()
time_stamp = time.strftime("%Y%m%d-%H%M%S")
- # plot paths
if plot_paths:
file_name = os.path.join(output_dir, output_name + '{}'.format(time_stamp))
plotnsave_paths(trace.trace, env=env, fileName_prefix=file_name)
diff --git a/robohive/logger/grouped_datasets.py b/robohive/logger/grouped_datasets.py
index f0c56d9b..911ddf07 100644
--- a/robohive/logger/grouped_datasets.py
+++ b/robohive/logger/grouped_datasets.py
@@ -179,7 +179,10 @@ def render(self, output_dir, output_format, groups:list, datasets:list, input_fp
for t in range(horizon):
# render single frame
for i_cam, cam_key in enumerate(datasets):
- frame_tile[:,i_cam*width:(i_cam+1)*width, :] = self.trace[grp][cam_key][t]
+ if cam_key.startswith('env_infos/visual_dict/d:'):
+ frame_tile[:,i_cam*width:(i_cam+1)*width, :] = self.trace[grp][cam_key][t].transpose(1,2,0)
+ else:
+ frame_tile[:,i_cam*width:(i_cam+1)*width, :] = self.trace[grp][cam_key][t]
# process single frame
if output_format == "mp4":
frames[t,:,:,:] = frame_tile
@@ -387,9 +390,13 @@ def load(trace_path, trace_type=TraceType.UNSET):
trace.root[trace.name] = trace.trace # build root
else:
file_data = pickle.load(open(trace_path, 'rb'))
- trace = Trace(name=list(file_data.keys())[0])
- trace.trace = file_data[trace.name] # load data
- trace.root = file_data # build root
+
+ try:
+ trace = Trace(name=list(file_data.keys())[0])
+ trace.trace = file_data[trace.name] # load data
+ trace.root = file_data # build root
+ except:
+ trace = file_data
trace.trace_type=TraceType.get_type(trace_type)
return trace
diff --git a/robohive/robot/dynamixel_py.py b/robohive/robot/dynamixel_py.py
new file mode 100644
index 00000000..4cb409b9
--- /dev/null
+++ b/robohive/robot/dynamixel_py.py
@@ -0,0 +1,634 @@
+import os, ctypes
+import time
+import numpy as np
+# os.sys.path.append('../dynamixel_functions_py') # Path setting
+import dynamixel_functions as dynamixel # Uses Dynamixel SDK library
+import click
+
+
+class Dynamixel_X():
+ def __init__(self):
+ # Control table address
+ self.ADDR_TORQUE_ENABLE = 64 # Control table address is different in Dynamixel model
+ self.ADDR_GOAL_POSITION = 116
+ self.ADDR_PRESENT_POSITION = 132
+ self.ADDR_PRESENT_VELOCITY = 128
+ self.ADDR_PRESENT_POS_VEL = 128 # Trick to get position and velocity at once
+ self.ADDR_MAX_VELOCITY = 44
+ self.ADDR_HARDWARE_ERROR = 70
+
+ # control mode options
+ self.ADDR_OPERATION_MODE = 11
+ self.ADDR_GOAL_TORQUE = 102 # Lowest byte of goal torque value
+
+ # Data Byte Length
+ self.LEN_PRESENT_POSITION = 4
+ self.LEN_PRESENT_VELOCITY = 4
+ self.LEN_PRESENT_POS_VEL = 8
+ self.LEN_GOAL_POSITION = 4
+ self.LEN_GOAL_TORQUE = 2
+
+
+class Dynamixel_MX():
+ def __init__(self):
+ # Control table address
+ self.ADDR_TORQUE_ENABLE = 24 # Control table address is different in Dynamixel model
+ self.ADDR_GOAL_POSITION = 30
+ self.ADDR_PRESENT_POSITION = 36
+ self.ADDR_PRESENT_VELOCITY = 38
+ self.ADDR_PRESENT_POS_VEL = 36 # Trick to get position and velocity at once
+ self.ADDR_MAX_VELOCITY = 44
+ self.ADDR_HARDWARE_ERROR = 70
+
+ # torque control mode options (left over from P1)
+ self.ADDR_TORQUE_CONTROL_MODE = 70
+ self.ADDR_GOAL_TORQUE = -1 # torque mode not supported
+
+ # Data Byte Length
+ self.LEN_PRESENT_POSITION = 2
+ self.LEN_PRESENT_VELOCITY = 2
+ self.LEN_PRESENT_POS_VEL = 4
+ self.LEN_GOAL_POSITION = 2
+ self.LEN_GOAL_TORQUE = 2
+
+DXL_NULL_TORQUE_VALUE = 0
+DXL_MIN_CW_TORQUE_VALUE = 1024
+DXL_MAX_CW_TORQUE_VALUE = 2047
+DXL_MIN_CCW_TORQUE_VALUE = 0
+DXL_MAX_CCW_TORQUE_VALUE = 1023
+
+# Settings for MX28
+POS_SCALE = 2*np.pi/4096 #(=.088 degrees)
+VEL_SCALE = 0.229 * 2 * np.pi / 60 #(=0.229rpm)
+
+TORQUE_ENABLE = 1 # Value for enabling the torque
+TORQUE_DISABLE = 0 # Value for disabling the torque
+DXL_MINIMUM_POSITION_VALUE = 100 # Dynamixel will rotate between this value
+DXL_MAXIMUM_POSITION_VALUE = 4000 # and this value (note that the Dynamixel would not move when the position value is out of movable range. Check e-manual about the range of the Dynamixel you use.)
+DXL_MOVING_STATUS_THRESHOLD = 15 # Dynamixel moving status threshold
+
+# ESC_ASCII_VALUE = 0x1b
+
+COMM_SUCCESS = 0 # Communication Success result value
+# COMM_TX_FAIL = -1001 # Communication Tx Failed
+
+
+
+class dxl():
+
+ # devicename: Port name being used on your controller # ex) Windows: "COM1" Linux: "/dev/ttyUSB0" Mac: "/dev/tty.usbserial-*"
+ def __init__(self, motor_id, motor_type="X", baudrate=1000000, devicename="/dev/ttyUSB0", protocol=2):
+
+
+ self.motor_id = motor_id
+ self.motor_type = motor_type
+ self.baudrate = baudrate
+ self.devicename = devicename
+ self.protocol = protocol
+ self.n_motors = len(motor_id)
+
+ if motor_type == "MX":
+ self.motor = Dynamixel_MX()
+ elif motor_type == "X":
+ self.motor = Dynamixel_X()
+ else:
+ quit("Motor type not recognized")
+
+ # default mode
+ self.ctrl_mode = TORQUE_DISABLE
+
+ # Initialize PortHandler Structs
+ # Set the port path and Get methods and members of PortHandlerLinux or PortHandlerWindows
+ self.port_num = dynamixel.portHandler(self.devicename.encode('utf-8'))
+
+ # Initialize PacketHandler Structs
+ dynamixel.packetHandler()
+
+
+ def open_port(self):
+ # Open port
+ if dynamixel.openPort(self.port_num):
+ print("Succeeded to open the port!")
+ else:
+ print("Failed to open the port %s"%self.devicename)
+ os.system("sudo chmod a+rw %s"%self.devicename)
+ print("Editing permissions and trying again")
+ if dynamixel.openPort(self.port_num):
+ print("Succeeded to open the port!")
+ else:
+ quit("Failed to open the port! Run following command and try again.\nsudo chmod a+rw %s"%self.devicename)
+
+ # Set port baudrate
+ if dynamixel.setBaudRate(self.port_num, self.baudrate):
+ print("Succeeded to change the baudrate!")
+ else:
+ quit("Failed to change the baudrate!")
+
+ # Enable Dynamixel Torque
+ self.engage_motor(self.motor_id, True)
+
+ # Initialize Group instance
+
+ # controls
+ self.group_desPos = dynamixel.groupSyncWrite(self.port_num, self.protocol, self.motor.ADDR_GOAL_POSITION, self.motor.LEN_GOAL_POSITION)
+ self.group_desTor = dynamixel.groupSyncWrite(self.port_num, self.protocol, self.motor.ADDR_GOAL_TORQUE, self.motor.LEN_GOAL_TORQUE) # NOTE: not all motors support them
+
+ # positions
+ self.group_pos = dynamixel.groupBulkRead(self.port_num, self.protocol)
+ for m_id in self.motor_id:
+ dxl_addparam_result = ctypes.c_ubyte(dynamixel.groupBulkReadAddParam(self.group_pos, m_id, self.motor.ADDR_PRESENT_POSITION, self.motor.LEN_PRESENT_POSITION)).value
+ if dxl_addparam_result != 1:
+ print("[ID:%03d] groupBulkRead addparam_posfailed" % (m_id))
+ quit()
+
+ # velocities
+ self.group_vel = dynamixel.groupBulkRead(self.port_num, self.protocol)
+ for m_id in self.motor_id:
+ dxl_addparam_result = ctypes.c_ubyte(dynamixel.groupBulkReadAddParam(self.group_vel, m_id, self.motor.ADDR_PRESENT_VELOCITY, self.motor.LEN_PRESENT_VELOCITY)).value
+ if dxl_addparam_result != 1:
+ print("[ID:%03d] groupBulkRead addparam_vel failed" % (m_id))
+ quit()
+
+ # positions and velocities
+ self.group_pos_vel = dynamixel.groupBulkRead(self.port_num, self.protocol)
+ for m_id in self.motor_id:
+ dxl_addparam_result = ctypes.c_ubyte(dynamixel.groupBulkReadAddParam(self.group_pos_vel, m_id, self.motor.ADDR_PRESENT_POS_VEL, self.motor.LEN_PRESENT_POS_VEL)).value
+ if dxl_addparam_result != 1:
+ print("[ID:%03d] groupBulkRead addparam_posfailed" % (m_id))
+ quit()
+
+ # buffers
+ self.dxl_present_position = float('nan')*np.zeros(self.n_motors)
+ self.dxl_present_velocity = float('nan')*np.zeros(self.n_motors)
+ self.dxl_last_position = float('nan')*np.zeros(self.n_motors)
+ self.dxl_last_velocity = float('nan')*np.zeros(self.n_motors)
+ print("Dynamixels successfully connected")
+
+
+ # Cheak health
+ def okay(self, motor_id=None):
+ if motor_id is None:
+ motor_id = self.motor_id.copy()
+ dxl_comm_result = dynamixel.getLastTxRxResult(self.port_num, self.protocol)
+ dxl_error = dynamixel.getLastRxPacketError(self.port_num, self.protocol)
+
+ if(dxl_comm_result != COMM_SUCCESS) or (dxl_error != COMM_SUCCESS):
+ # Print apprpriate error
+ if dxl_comm_result != COMM_SUCCESS:
+ print("\n" + str(dynamixel.getTxRxResult(self.protocol, dxl_comm_result)))
+ if dxl_error != COMM_SUCCESS:
+ print("\n" + str(dynamixel.getRxPacketError(self.protocol, dxl_error)) + ". Error_id:" + str(dxl_error))
+
+ # print hardware status
+ print("Motor id(hardware status): [ ", end='')
+ for m_id in motor_id:
+ print("%d(%d), " % (m_id, dynamixel.read1ByteTxRx(self.port_num, self.protocol,\
+ m_id, self.motor.ADDR_HARDWARE_ERROR)), end='')
+ print("]", flush=True)
+ return False
+ else:
+ return True
+
+
+ # Engage/ Disengae the motors. enable = True/ False
+ def engage_motor(self, motor_id, enable):
+ for dxl_id in motor_id:
+
+ # fault handelling
+ while(True):
+ dynamixel.write1ByteTxRx(self.port_num, self.protocol, dxl_id, self.motor.ADDR_TORQUE_ENABLE, enable)
+ if(self.okay([dxl_id])):
+ break
+ else:
+ print('dxl%d: Error with ADDR_TORQUE_ENABLE. Retrying after reboot ...' %dxl_id, flush=True)
+ dynamixel.reboot(self.port_num, self.protocol, dxl_id)
+ time.sleep(0.25) # Pause for reboot
+
+
+ # Returns pos in radians and velocity in radian/ sec
+ def get_pos_vel_old(self, motor_id):
+
+ dxl_present_position = []
+ dxl_present_velocity = []
+
+ # Bulkread present positions
+ dynamixel.groupBulkReadTxRxPacket(self.group_pos_vel)
+
+ # Retrieve data
+ for i in range(self.n_motors):
+ dxl_id = motor_id[i]
+ # Get present position value
+ dxl_getdata_result = ctypes.c_ubyte(dynamixel.groupBulkReadIsAvailable(self.group_pos_vel, dxl_id, self.motor.ADDR_PRESENT_POS_VEL, self.motor.LEN_PRESENT_POS_VEL)).value
+ if dxl_getdata_result != 1:
+ print("[ID:%03d] groupBulkRead get_pos_vel failed" % (dxl_id))
+ dxl_present_position.append(float('nan'))
+ dxl_present_velocity.append(float('nan'))
+ # quit()
+ else:
+ dxl_present_position.append(dynamixel.groupBulkReadGetData(self.group_pos_vel, dxl_id, self.motor.ADDR_PRESENT_POSITION, self.motor.LEN_PRESENT_POSITION))
+ dxl_present_velocity.append(dynamixel.groupBulkReadGetData(self.group_pos_vel, dxl_id, self.motor.ADDR_PRESENT_VELOCITY, self.motor.LEN_PRESENT_VELOCITY))
+
+ dxl_present_velocity = np.array(dxl_present_velocity)
+ for i in range(len(dxl_present_velocity)):
+ if(dxl_present_velocity[i]>=1024):
+ dxl_present_velocity[i] = -1.*(dxl_present_velocity[i] - 1024)
+ return POS_SCALE*np.array(dxl_present_position), VEL_SCALE*np.array(dxl_present_velocity)
+
+
+ # Returns pos in radians and velocity in radian/ sec
+ def get_pos_vel(self, motor_id):
+
+ # Bulkread present positions
+ dynamixel.groupBulkReadTxRxPacket(self.group_pos_vel)
+ if(not self.okay(motor_id)):
+ print("try one more time. If not, we will spoof packets below ====================== ")
+ # try one more time. If not, we will spoof packets below.
+ dynamixel.groupBulkReadTxRxPacket(self.group_pos_vel)
+
+ dxl_errored = []
+ # Retrieve data
+ for i in range(self.n_motors):
+ dxl_id = motor_id[i]
+
+ # Get present position value
+ dxl_getdata_result = ctypes.c_ubyte(dynamixel.groupBulkReadIsAvailable(self.group_pos_vel, dxl_id, self.motor.ADDR_PRESENT_POS_VEL, self.motor.LEN_PRESENT_POS_VEL)).value
+ if dxl_getdata_result != 1:
+ #send last known values
+ dxl_errored.append(dxl_id)
+
+ self.dxl_present_position[i] = self.dxl_last_position[i].copy()
+ self.dxl_present_velocity[i] = self.dxl_last_velocity[i].copy()
+ else:
+ self.dxl_last_position[i] = self.dxl_present_position[i].copy()
+ self.dxl_last_velocity[i] = self.dxl_present_velocity[i].copy()
+
+ dxl_present_position = dynamixel.groupBulkReadGetData(self.group_pos_vel, dxl_id, self.motor.ADDR_PRESENT_POSITION, self.motor.LEN_PRESENT_POSITION)
+ dxl_present_velocity = dynamixel.groupBulkReadGetData(self.group_pos_vel, dxl_id, self.motor.ADDR_PRESENT_VELOCITY, self.motor.LEN_PRESENT_VELOCITY)
+ if(dxl_present_velocity>=1024):
+ dxl_present_velocity = -1.*(dxl_present_velocity - 1024)
+
+ self.dxl_present_position[i] = POS_SCALE*dxl_present_position
+ self.dxl_present_velocity[i] = VEL_SCALE*dxl_present_velocity
+
+ if len(dxl_errored):
+ self.okay(motor_id)
+ print("groupBulkRead get_pos_vel failed. Sending last known values for dynamixel ids: " + str(dxl_errored),flush=True)
+ return self.dxl_present_position.copy(), self.dxl_present_velocity.copy()
+
+
+ # Returns pos in radians
+ def get_pos(self, motor_id):
+ dxl_present_position = []
+
+ # Bulkread present positions
+ dynamixel.groupBulkReadTxRxPacket(self.group_pos)
+
+ # Retrieve data
+ for dxl_id in motor_id:
+ # Get present position value
+ dxl_getdata_result = ctypes.c_ubyte(dynamixel.groupBulkReadIsAvailable(\
+ self.group_pos, dxl_id, self.motor.ADDR_PRESENT_POSITION, self.motor.LEN_PRESENT_POSITION)).value
+ if dxl_getdata_result != 1:
+ print("[ID:%03d] groupBulkRead pos_getdata failed" % (dxl_id))
+ dxl_present_position.append(0)
+ quit()
+ else:
+ dxl_present_position.append(dynamixel.groupBulkReadGetData(\
+ self.group_pos, dxl_id, self.motor.ADDR_PRESENT_POSITION,\
+ self.motor.LEN_PRESENT_POSITION))
+
+ return POS_SCALE*np.array(dxl_present_position)
+
+
+ # Returns vel in radians/sec
+ def get_vel(self, motor_id):
+ dxl_present_velocity = []
+
+ dynamixel.groupBulkReadTxRxPacket(self.group_vel)
+ for dxl_id in motor_id:
+ # Get present velocity value
+ dxl_getdata_result = ctypes.c_ubyte(dynamixel.groupBulkReadIsAvailable(\
+ self.group_vel, dxl_id, self.motor.ADDR_PRESENT_VELOCITY, self.motor.LEN_PRESENT_VELOCITY)).value
+ if dxl_getdata_result != 1:
+ print("[ID:%03d] groupBulkRead vel_getdata failed" % (dxl_id))
+ dxl_present_velocity.append(0)
+ quit()
+ else:
+ dxl_present_velocity.append(dynamixel.groupBulkReadGetData(\
+ self.group_vel, dxl_id, self.motor.ADDR_PRESENT_VELOCITY, self.motor.LEN_PRESENT_VELOCITY))
+
+ dxl_present_velocity = np.array(dxl_present_velocity)
+ for i in range(len(dxl_present_velocity)):
+ if(dxl_present_velocity[i]>=1024):
+ dxl_present_velocity[i] = -1.*(dxl_present_velocity[i] - 1024)
+
+ return VEL_SCALE*dxl_present_velocity
+
+
+ # Returns pos in radians
+ def getIndividual_pos(self, motor_id):
+ dxl_present_position = []
+
+ # Read present position and velocity
+ for dxl_id in motor_id:
+ dxl_present_position.append(dynamixel.read2ByteTxRx(self.port_num,\
+ self.protocol, dxl_id, self.motor.ADDR_PRESENT_POSITION))
+ if (not self.okay(motor_id)):
+ self.close(motor_id)
+ quit('error getting self.motor.ADDR_PRESENT_POSITION')
+ return POS_SCALE*np.array(dxl_present_position)
+
+
+ # Returns vel in radians/sec
+ def getIndividual_vel(self, motor_id):
+ dxl_present_velocity = []
+ # Read present position
+ for dxl_id in motor_id:
+ dxl_present_velocity.append(dynamixel.read2ByteTxRx(self.port_num, self.protocol, dxl_id, self.motor.ADDR_PRESENT_VELOCITY))
+ if (not self.okay(motor_id)):
+ self.close(motor_id)
+ quit('error getting self.motor.ADDR_PRESENT_VELOCITY')
+
+ dxl_present_velocity = np.array(dxl_present_velocity)
+
+ for i in range(len(dxl_present_velocity)):
+ if(dxl_present_velocity[i]>=1024):
+ dxl_present_velocity[i] = -1.*(dxl_present_velocity[i] - 1024)
+
+ return VEL_SCALE*dxl_present_velocity
+
+
+ # Expects des_pos in radians
+ def setIndividual_des_pos(self, motor_id, des_pos_inRadians):
+ # if in torque mode, activate position control mode
+ if(self.ctrl_mode == TORQUE_ENABLE):
+ for dxl_id in motor_id:
+ dynamixel.write1ByteTxRx(self.port_num, self.protocol, dxl_id, self.motor.ADDR_TORQUE_CONTROL_MODE, TORQUE_DISABLE)
+ if (not self.okay(motor_id)):
+ self.close(motor_id)
+ quit('error disabling ADDR_TORQUE_CONTROL_MODE')
+ self.ctrl_mode = TORQUE_DISABLE
+
+ # Write goal position
+ for i in range(len(motor_id)):
+ dynamixel.write4ByteTxRx(self.port_num, self.protocol, motor_id[i], self.motor.ADDR_GOAL_POSITION, int(des_pos_inRadians[i]/POS_SCALE))
+ if (not self.okay(motor_id)):
+ self.close(motor_id)
+ quit('error setting ADDR_GOAL_POSITION =====')
+
+
+ # Expects des_pos in radians (0-2*pi)
+ def set_des_pos(self, motor_id, des_pos_inRadians):
+
+ des_pos_inRadians = np.clip(des_pos_inRadians, 0.0, 2*np.pi)
+ # if in torque mode, activate position control mode
+ if(self.ctrl_mode == TORQUE_ENABLE):
+ for dxl_id in motor_id:
+ dynamixel.write1ByteTxRx(self.port_num, self.protocol, dxl_id, self.motor.ADDR_TORQUE_CONTROL_MODE, TORQUE_DISABLE)
+ if (not self.okay(motor_id)):
+ self.close(motor_id)
+ quit('error disabling self.motor.ADDR_TORQUE_CONTROL_MODE')
+ self.ctrl_mode = TORQUE_DISABLE
+
+ # Write goal position
+ for i in range(len(motor_id)):
+ dxl_addparam_result = ctypes.c_ubyte(dynamixel.groupSyncWriteAddParam(self.group_desPos, motor_id[i], int(des_pos_inRadians[i]/POS_SCALE), self.motor.LEN_GOAL_POSITION)).value
+ if dxl_addparam_result != 1:
+ print(dxl_addparam_result)
+ print("[ID:%03d] groupSyncWrite addparam failed" % (motor_id[i]))
+ self.close(motor_id)
+ quit()
+
+ # Syncwrite goal position
+ dynamixel.groupSyncWriteTxPacket(self.group_desPos)
+ if(not self.okay(motor_id)):
+ self.close(motor_id)
+ quit('error bulk commanding desired positions')
+
+ # Clear syncwrite parameter storage
+ dynamixel.groupSyncWriteClearParam(self.group_desPos)
+
+
+ # Set desired torques, only for MX64
+ def set_des_torque(self, motor_id, des_tor):
+ # If in position mode, activate torque mode
+ if(self.ctrl_mode == TORQUE_DISABLE):
+ for dxl_id in motor_id:
+ dynamixel.write1ByteTxRx(self.port_num, self.protocol, dxl_id, self.motor.ADDR_TORQUE_CONTROL_MODE, TORQUE_ENABLE)
+ if (not self.okay(motor_id)):
+ self.close(motor_id)
+ quit('error enabling ADDR_TORQUE_CONTROL_MODE')
+ self.ctrl_mode = TORQUE_ENABLE
+
+ # Write goal position
+ for i in range(len(motor_id)):
+ dxl_addparam_result = ctypes.c_ubyte(dynamixel.groupSyncWriteAddParam(self.group_desTor, motor_id[i], int(des_tor[i]), self.motor.LEN_GOAL_TORQUE)).value
+ if dxl_addparam_result != 1:
+ print(dxl_addparam_result)
+ print("[ID:%03d] groupSyncWrite addparam failed" % (motor_id[i]))
+ self.close(motor_id)
+ quit()
+
+ # Syncwrite goal position
+ dynamixel.groupSyncWriteTxPacket(self.group_desTor)
+ if(not self.okay(motor_id)):
+ self.close(motor_id)
+ quit('error bulk commanding desired torques')
+
+ # Clear syncwrite parameter storage
+ dynamixel.groupSyncWriteClearParam(self.group_desTor)
+
+
+ # Set desired torques, only for MX64
+ def setIndividual_des_torque(self, motor_id, des_tor):
+ # If in position mode, activate torque mode
+ if(self.ctrl_mode == TORQUE_DISABLE):
+ for dxl_id in motor_id:
+ dynamixel.write1ByteTxRx(self.port_num, self.protocol, dxl_id, self.motor.ADDR_TORQUE_CONTROL_MODE, TORQUE_ENABLE)
+ if (not self.okay(motor_id)):
+ self.close(motor_id)
+ quit('error enabling ADDR_TORQUE_CONTROL_MODE')
+ self.ctrl_mode = TORQUE_ENABLE
+
+ # Write goal position
+ for i in range(len(motor_id)):
+ dynamixel.write2ByteTxRx(self.port_num, self.protocol, motor_id[i], self.motor.ADDR_GOAL_TORQUE, int(des_tor[i]))
+ if (not self.okay(motor_id)):
+ self.close(motor_id)
+ quit('error setting ADDR_GOAL_TORQUE')
+
+
+ # Set maximum velocity
+ def set_max_vel(self, motor_id, max_vel):
+ for dxl_id in motor_id:
+ dynamixel.write4ByteTxRx(self.port_num, self.protocol, dxl_id, self.motor.ADDR_MAX_VELOCITY, max_vel)
+ if (not self.okay(motor_id)):
+ self.close(motor_id)
+ quit('error setting self.motor.ADDR_MAX_VELOCITY')
+
+ # Close connection
+ def close(self, motor_id):
+
+ if self.port_num is not None:
+ # Disengage Dynamixels
+ self.engage_motor(motor_id, False)
+
+ # Close port
+ dynamixel.closePort(self.port_num)
+ self.port_num = None # mark as closed
+
+ return True
+
+ def __del__(self):
+ self.close(self.motor_id)
+
+
+DESC = '''
+USAGE:
+python dynamixel_py.py --motor_id "[6,8]" --motor_type "MX" --baudrate 1000000 --device /dev/ttyUSB0 --protocol 2
+'''
+@click.command(help=DESC)
+@click.option('--motor_id', '-i', type=str, help='motor ids', default="[1, 2]")
+@click.option('--motor_type', '-t', type=str, help='motor type', default="X")
+@click.option('--baudrate', '-b', type=int, help='port baud rate', default=1000000)
+@click.option('--device', '-n', type=str, help='port name', default="/dev/ttyUSB0")
+@click.option('--protocol', '-p', type=int, help='communication protocol 1/2', default=2)
+def main(motor_id, motor_type, device, baudrate, protocol):
+
+ dxl_goal_position = [DXL_MINIMUM_POSITION_VALUE*POS_SCALE, DXL_MAXIMUM_POSITION_VALUE*POS_SCALE] # Goal position
+ index = 0
+
+ dxl_ids = eval(motor_id)
+ dy = dxl(motor_id=dxl_ids, motor_type=motor_type, baudrate=baudrate, devicename=device, protocol=protocol)
+ dy.open_port()
+
+ # Test timing ==================================
+ cnt = 10
+ print("Testing timings (avg over %d trials for %d motors) -------------"% (cnt, len(dxl_ids)))
+ t_s = time.time()
+ for i in range(cnt):
+ dxl_present_position, dxl_present_velocity = dy.get_pos_vel(dxl_ids)
+ t_e = time.time()
+ print("Bulk [pos+vel] read takes:\t\t %0.5f sec **BEST**" % ((t_e-t_s)/float(cnt)))
+
+ t_s = time.time()
+ for i in range(cnt):
+ dxl_present_position = dy.get_pos(dxl_ids)
+ dxl_present_velocity = dy.get_vel(dxl_ids)
+ t_e = time.time()
+ print("Bulk [pos,vel] read takes:\t\t %0.4f sec" % ((t_e-t_s)/float(cnt)))
+
+ t_s = time.time()
+ for i in range(cnt):
+ dxl_present_position = dy.getIndividual_pos(dxl_ids)
+ dxl_present_velocity = dy.getIndividual_vel(dxl_ids)
+ t_e = time.time()
+ print("Individual [pos,vel] read takes:\t %0.5f sec" % ((t_e-t_s)/float(cnt)))
+
+ t_s = time.time()
+ for i in range(cnt):
+ dxl_present_position, dxl_present_velocity = dy.get_pos_vel(dxl_ids)
+ dy.set_des_pos(dxl_ids, dxl_present_position)
+ t_e = time.time()
+ print("Bulk [pos+vel,ctrl] loop takes:\t\t %0.5f sec **BEST**" % ((t_e-t_s)/float(cnt)))
+
+ t_s = time.time()
+ for i in range(cnt):
+ dxl_present_position = dy.get_pos(dxl_ids)
+ dxl_present_velocity = dy.get_vel(dxl_ids)
+ dy.set_des_pos(dxl_ids, dxl_present_position)
+ t_e = time.time()
+ print("Bulk [pos,vel,ctrl] loop takes:\t\t %0.5f sec" % ((t_e-t_s)/float(cnt)))
+
+ t_s = time.time()
+ for i in range(cnt):
+ dxl_present_position = dy.getIndividual_pos(dxl_ids)
+ dxl_present_velocity = dy.getIndividual_vel(dxl_ids)
+ dy.setIndividual_des_pos(dxl_ids, dxl_present_position)
+ t_e = time.time()
+ print("Individual [pos,vel,ctrl] takes:\t %0.5f sec" % ((t_e-t_s)/float(cnt)))
+
+
+ # Test reads ==================================
+ dy.engage_motor(dxl_ids, False)
+ print("Motor disengaged")
+ print("Testing position and velocity --------------")
+ input("Press enter and apply external forces")
+ for i in range(cnt):
+ dxl_present_position, dxl_present_velocity = dy.get_pos_vel(dxl_ids)
+ for j in range(len(dxl_ids)):
+ print("cnt:%03d, dxl_id:%01d ==> Pos:%2.2f, Vel:%1.3f" % (i, dxl_ids[j], dxl_present_position[j], dxl_present_velocity[j]))
+ dy.engage_motor(dxl_ids, True)
+ # dy.set_max_vel(dxl_ids, 0) # 1-1023, 0:max_rpm
+ print("Motor engaged")
+
+
+
+ # Test torque mode =============================
+ if(0): #only for MX64s
+ print("Zero Torque")
+ dy.set_des_torque(dxl_ids, 0)
+ time.sleep(1)
+
+
+ print("Max CCW Torque")
+ dy.set_des_torque(dxl_ids, DXL_MAX_CCW_TORQUE_VALUE)
+ for i in range(50):
+ dxl_present_position = dy.get_pos(dxl_ids)
+ for j in range(len(dxl_ids)):
+ print("cnt:%03d, dxl_id:%01d ==> Pos:%2.2f, Vel:%1.3f" % (i, dxl_ids[j], dxl_present_position[j], dxl_present_velocity[j]))
+
+ print("Zero Torque")
+ dy.set_des_torque(dxl_ids, 0)
+ time.sleep(1)
+
+ print("Max CW Torque")
+ dy.set_des_torque(dxl_ids, DXL_MAX_CW_TORQUE_VALUE)
+ for i in range(50):
+ dxl_present_position = dy.get_pos(dxl_ids)
+ for j in range(len(dxl_ids)):
+ print("cnt:%03d, dxl_id:%01d ==> Pos:%2.2f, Vel:%1.3f" % (i, dxl_ids[j], dxl_present_position[j], dxl_present_velocity[j]))
+
+
+ print("Zero Torque")
+ dy.set_des_torque(dxl_ids, 0)
+ time.sleep(1)
+
+
+ # Test position mode =============================
+ while 1:
+ cnt = 0
+ # wait for user input
+ user = input("Press ENTER to continue! (or press q+ENTER to quit!)")
+ if user == 'q':
+ break
+
+ # set goal position
+ dy.set_des_pos(dxl_ids, dxl_goal_position[index]*np.ones(len(dxl_ids)))
+
+
+ # wait and read sensors
+ while 1:
+ dxl_present_position = dy.get_pos(dxl_ids)
+ dxl_present_velocity = dy.get_vel(dxl_ids)
+
+ for j in range(len(dxl_ids)):
+ print("cnt:%03d, dxl_id:%01d ==> GoalPos:%2.2f, Pos:%2.2f, Vel:%1.3f" % (cnt, dxl_ids[j], dxl_goal_position[index], dxl_present_position[j], dxl_present_velocity[j]))
+
+ cnt = cnt + 1
+ if not (abs(dxl_goal_position[index] - dxl_present_position[0]) > DXL_MOVING_STATUS_THRESHOLD): # checking only the first motor
+ break
+
+ # Change goal position
+ if index == 0:
+ index = 1
+ else:
+ index = 0
+
+ # Close connection and exit
+ dy.close(dxl_ids)
+ print('successful exit')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/robohive/robot/hardware_robotiq.py b/robohive/robot/hardware_robotiq.py
index 27b4e2f0..e50a5cf0 100644
--- a/robohive/robot/hardware_robotiq.py
+++ b/robohive/robot/hardware_robotiq.py
@@ -98,7 +98,7 @@ def get_sensors(self):
return self.get_sensors()
return np.array([curr_state.width])
- def apply_commands(self, width:float, speed:float=0.1, force:float=0.1):
+ def apply_commands(self, width:float, speed:float=0.4, force:float=0.4):
assert width>=0.0 and width<=self.max_width, "Gripper desired width ({}) is out of bound (0,{})".format(width, self.max_width)
self.robot.goto(width=width, speed=speed, force=force)
return 0
diff --git a/robohive/robot/robot.py b/robohive/robot/robot.py
index f3df43a3..bce139b7 100644
--- a/robohive/robot/robot.py
+++ b/robohive/robot/robot.py
@@ -49,6 +49,7 @@ def __init__(self,
sensor_cache_maxsize = 5, # cache size for sensors
noise_scale = 0, # scale for sensor noise
random_generator = None, # random number generator
+ obs_delay = 0, # timesteps to delays observations by
**kwargs,
):
@@ -63,10 +64,14 @@ def __init__(self,
self.np_random = np.random
else:
self.np_random = random_generator
+ self.obs_delay = obs_delay
+ assert(self.obs_delay < self._sensor_cache_maxsize)
+ assert(self.obs_delay >= 0)
# sensor cache
self._sensor_cache = deque([], maxlen=self._sensor_cache_maxsize)
-
+ self._img_cache = deque([], maxlen=self._sensor_cache_maxsize)
+ self._depth_cache = deque([], maxlen=self._sensor_cache_maxsize)
# create robot sim
if mj_sim is None:
# (creates new robot everytime to facilitate parallelization)
@@ -120,7 +125,7 @@ def hardware_init(self, robot_config):
prompt("Initializing device: %s"%(name), 'white', 'on_grey')
if device['interface']['type'] == 'dynamixel':
# initialize dynamixels
- from dynamixel_py import dxl
+ from robohive.robot.dynamixel_py import dxl
ids = np.unique([device['sensor_ids'] + device['actuator_ids']]).tolist()
device['robot'] = dxl(motor_id=ids, motor_type=\
device['interface']['motor_type'], devicename= device['interface']['name'])
@@ -162,8 +167,8 @@ def hardware_init(self, robot_config):
device['robot'].open_port()
# set actuator mode
- for actuator in device['actuator']:
- device['robot'].set_operation_mode(motor_id=[actuator['hdr_id']], mode=actuator['mode'])
+ #for actuator in device['actuator']:
+ # device['robot'].set_operation_mode(motor_id=[actuator['hdr_id']], mode=actuator['mode'])
# engage motors
device['robot'].engage_motor(motor_id=device['actuator_ids'], enable=True)
@@ -353,10 +358,13 @@ def configure_robot(self, sim, config_path):
# refresh the sensor cache
def _sensor_cache_refresh(self):
+ self._img_cache = deque([], maxlen=self._sensor_cache_maxsize)
+ self._depth_cache = deque([], maxlen=self._sensor_cache_maxsize)
for _ in range(self._sensor_cache_maxsize):
self.get_sensors()
+
# get past sensor
def get_sensor_from_cache(self, index=-1):
assert (index>=0 and index len(self._sensor_cache):
+ cache_idx += 1
+ return self._sensor_cache[cache_idx]
# get sensor data and update robot time accordingly
@@ -447,14 +459,32 @@ def get_visual_sensors(self, height:int, width:int, cameras:list, device_id:int,
else:
imgs = np.zeros((len(cameras), height, width, 3), dtype=np.uint8)
depths = np.zeros((len(cameras), height, width))
+
for ind, cam in enumerate(cameras):
# img, depth = sim.render(width=width, height=height, depth=True, mode='offscreen', camera_name=cam, device_id=device_id)
+ device = self.robot_config[cam]
+ assert device['cam'][0]['hdr_id'] == 'rgb'
+ assert device['cam'][1]['hdr_id'] == 'd'
img, depth = sim.renderer.render_offscreen(width=width, height=height, depth=True, camera_id=cam, device_id=device_id)
+
+ if self._noise_scale!=0:
+
+ img = img.astype(float) + self._noise_scale * device['cam'][0]['noise']*self.np_random.normal(size=img.shape)
+ img = np.clip(img, 0, 255).astype(np.uint8)
+ depth += self._noise_scale * device['cam'][1]['noise']*self.np_random.normal(size=depth.shape)
+ depth = np.clip(depth, 0, 1.0)
+
# img = img[::-1, :, :] # Image has to be flipped
imgs[ind, :, :, :] = img
- depths[ind, :, :] = depth
+ depths[ind, :, :] = 255*depth[::-1]
- return imgs, depths
+ self._img_cache.append(imgs)
+ self._depth_cache.append(depths)
+
+ cache_idx = -1-self.obs_delay
+ while -1*cache_idx > len(self._img_cache):
+ cache_idx += 1
+ return self._img_cache[cache_idx], self._depth_cache[cache_idx]
# Propagate sensor values back through the sim.
@@ -467,7 +497,8 @@ def sensor2sim(self, sensor, sim):
(2) can be used to feed noisy sim sensors back into the robot-sim. Note: Be careful, sim might not be stable for simulation after
"""
if not self.is_hardware and (self._noise_scale!=0):
- print("WARNING: Propagating noisy sensors back to sim can destablize simulation")
+ pass
+ #print("WARNING: Propagating noisy sensors back to sim can destablize simulation")
sim.data.time = sensor['time']
for name, device in self.robot_config.items():
@@ -817,4 +848,4 @@ def main():
rob.close()
if __name__ == '__main__':
- main()
\ No newline at end of file
+ main()
diff --git a/robohive/robot/serdes.py b/robohive/robot/serdes.py
index b7ecff60..155c42a3 100644
--- a/robohive/robot/serdes.py
+++ b/robohive/robot/serdes.py
@@ -14,6 +14,6 @@ def get_capnp_msgs(msgpkg):
print(f'capnp loading {msgpkg}')
filedir = os.path.dirname(os.path.abspath(__file__))
capnp_cache[msgpkg] = _schema_parser.load(
- os.path.join(filedir, f"/mnt/tmp_nfs_clientshare/.robopen/robopen/msgs/def/{msgpkg}.capnp"),
+ os.path.join(filedir, f"/mnt/nfs_code/.robopen/robopen/msgs/def/{msgpkg}.capnp"),
imports=site.getsitepackages())
- return capnp_cache[msgpkg]
\ No newline at end of file
+ return capnp_cache[msgpkg]
diff --git a/robohive/tutorials/ee_teleop_oculus.py b/robohive/tutorials/ee_teleop_oculus.py
index 01d5fd0e..1fdfe689 100644
--- a/robohive/tutorials/ee_teleop_oculus.py
+++ b/robohive/tutorials/ee_teleop_oculus.py
@@ -16,7 +16,7 @@
import numpy as np
import click
import gym
-from robohive.utils.quat_math import euler2quat, euler2mat, mat2quat, diffQuat, mulQuat
+from robohive.utils.quat_math import euler2quat, euler2mat, mat2quat, diffQuat, mulQuat, quat2euler
from robohive.utils.inverse_kinematics import IKResult, qpos_from_site_pose
from robohive.logger.roboset_logger import RoboSet_Trace
from robohive.logger.grouped_datasets import Trace as RoboHive_Trace
@@ -54,6 +54,7 @@ def vrbehind2mj(pose):
return pos, mat2quat(mat)
+# python tutorials/ee_teleop_oculus.py -e FrankaPlanarPushTeleop_v2d-v0 -ea "{'is_hardware': True}" -h 100 -r none -an 0.00 -rn 0.00 -o test.pickle -n 2 -f RoboHive
@click.command(help=DESC)
@click.option('-e', '--env_name', type=str, help='environment to load', default='rpFrankaRobotiqData-v0')
@click.option('-ea', '--env_args', type=str, default=None, help=('env args. E.g. --env_args "{\'is_hardware\':True}"'))
@@ -112,7 +113,7 @@ def main(env_name, env_args, reset_noise, action_noise, output, horizon, num_rol
# default actions
act = np.zeros(env.action_space.shape)
gripper_state = delta_gripper = 0
-
+ successes = 0
# Collect rollouts
for i_rollout in range(num_rollouts):
@@ -122,13 +123,27 @@ def main(env_name, env_args, reset_noise, action_noise, output, horizon, num_rol
# Reset
exit_request = False
reset_noise = reset_noise*np.random.uniform(low=-1, high=1, size=env.init_qpos.shape)
- env.reset(reset_qpos=env.init_qpos+reset_noise, blocking=True)
+ env.reset(reset_qpos=env.init_qpos+reset_noise)
+
+ # launch
+ print('hit pedal/button to start')
+ #while(getch.getch() not in ['a','b','c']): continue
+ while(True):
+ # poll input device --------------------------------------
+ buttons = oculus_reader.get_transformations_and_buttons()[1]
+ if buttons and buttons['A']:
+ break
+
+ time.sleep(.666)
+
+ print("\nrollout {} start".format(i_rollout))
+
# Reset goal site back to nominal position
env.sim.model.site_pos[goal_sid] = env.sim.data.site_xpos[teleop_sid]
env.sim.model.site_quat[goal_sid] = mat2quat(np.reshape(env.sim.data.site_xmat[teleop_sid], [3,-1]))
# recover init state
- obs, rwd, done, env_info = env.forward()
+ obs, rwd, done, env_info = env.forward(update_exteroception=True)
act = np.zeros(env.action_space.shape)
gripper_state = 0
@@ -184,7 +199,7 @@ def main(env_name, env_args, reset_noise, action_noise, output, horizon, num_rol
# target_quat[:] = mulQuat(euler2quat(rot_scale*delta_euler), target_quat)
# update desired gripper
gripper_state = gripper_scale*delta_gripper # TODO: Update to be delta
-
+ '''
# Find joint space solutions
ik_result = qpos_from_site_pose(
physics = env.sim,
@@ -204,7 +219,12 @@ def main(env_name, env_args, reset_noise, action_noise, output, horizon, num_rol
act = act + env.env.np_random.uniform(high=action_noise, low=-action_noise, size=len(act)).astype(act.dtype)
if env.normalize_act:
act = env.env.robot.normalize_actions(act)
-
+ '''
+ #print('target yaw: {}'.format(target_quat))
+ #print('target yaw: {}'.format(quat2euler(target_quat)))
+ act = np.concatenate([target_pos, quat2euler(target_quat), [gripper_state]])
+ act = 2*((act - env.pos_limits['eef_low'])/(np.abs(env.pos_limits['eef_high'] - env.pos_limits['eef_low'])+1e-8)-0.5)
+ act = np.clip(act, -1,1)
# nan actions for last log entry
act = np.nan*np.ones(env.action_space.shape) if i_step == horizon else act
@@ -222,11 +242,14 @@ def main(env_name, env_args, reset_noise, action_noise, output, horizon, num_rol
# step env using action from t=>t+1 ----------------------
if i_step < horizon: #incase last actions (nans) can cause issues in step
- obs, rwd, done, env_info = env.step(act)
+ obs, rwd, done, env_info = env.unwrapped.step(act, update_exteroception=True)
# Detect jumps
- qpos_now = env_info['obs_dict']['qp_arm']
- qpos_arm_err = np.linalg.norm(ik_result.qpos[:7]-qpos_now[:7])
+ try:
+ qpos_now = env_info['obs_dict']['qp_arm']
+ except:
+ qpos_now = env_info['obs_dict']['qp']
+ qpos_arm_err = np.linalg.norm(env.last_ctrl[:7]-qpos_now[:7])
if qpos_arm_err>0.5:
print("Jump detechted. Joint error {}. This is likely caused when hardware detects something unsafe. Resetting goal to where the arm curently is to avoid sudden jumps.".format(qpos_arm_err))
# Reset goal back to nominal position
@@ -234,12 +257,49 @@ def main(env_name, env_args, reset_noise, action_noise, output, horizon, num_rol
env.sim.model.site_quat[goal_sid] = mat2quat(np.reshape(env.sim.data.site_xmat[teleop_sid], [3,-1]))
print("rollout {} end".format(i_rollout))
- time.sleep(0.5)
+
+ # Move to pre-reset position
+ preset_pos = np.array([0.45, 0.375, 1.25])
+ preset_elr = np.array([ 3.14, 0.0, 0.78])
+ preset_grasp = np.array([0.0])
+ preset_action = np.concatenate([preset_pos, preset_elr, preset_grasp])
+ preset_action = 2*(((preset_action - env.pos_limits['eef_low'])/(np.abs(env.pos_limits['eef_high']-env.pos_limits['eef_low'])+1e-8))-0.5)
+ preset_i = 0
+
+ while preset_i < 50:
+
+ env.step(preset_action)
+ preset_i += 1
+
+ print('input result, A success / B fail')
+ while(True):
+ # poll input device --------------------------------------
+ buttons = oculus_reader.get_transformations_and_buttons()[1]
+ if buttons and buttons['A']:
+ user_cmt=1.0
+ successes += 1
+ break
+ elif buttons and buttons['B']:
+ user_cmt=0.0
+ break
+ elif buttons and buttons['rightTrig'][0]:
+ ans = input('corrupt??? (y for yes)')
+ if ans=='y':
+ user_cmt = -1.0
+ break
+
+
+ print(user_cmt)
+
+ for t in range(horizon+1):
+ trace.append_datums(group_key=group_key,dataset_key_val={'success':user_cmt})
+ print('Successes {}'.format(successes))
# save and close
env.close()
+ trace.close()
trace.save(output, verify_length=True)
-
+ print('Successes {}'.format(successes))
# render video outputs
if len(camera)>0:
if camera[0]!="default":
diff --git a/robohive/utils/examine_env.py b/robohive/utils/examine_env.py
index ea0dc03a..35a70ff5 100644
--- a/robohive/utils/examine_env.py
+++ b/robohive/utils/examine_env.py
@@ -12,6 +12,7 @@
import pickle
import time
import os
+import importlib
DESC = '''
Helper script to examine an environment and associated policy for behaviors; \n
@@ -32,6 +33,13 @@ def get_action(self, obs):
# return self.env.np_random.uniform(high=self.env.action_space.high, low=self.env.action_space.low)
return self.env.action_space.sample(), {'mode': 'random samples'}
+def load_class_from_str(module_name, class_name):
+ try:
+ m = __import__(module_name, globals(), locals(), class_name)
+ return getattr(m, class_name)
+ except (ImportError, AttributeError):
+ return None
+
# MAIN =========================================================
@click.command(help=DESC)
@click.option('-e', '--env_name', type=str, help='environment to load', required= True)
@@ -57,13 +65,20 @@ def main(env_name, policy_path, mode, seed, num_episodes, render, camera_name, o
# resolve policy and outputs
if policy_path is not None:
- pi = pickle.load(open(policy_path, 'rb'))
- if output_dir == './': # overide the default
- output_dir, pol_name = os.path.split(policy_path)
- output_name = os.path.splitext(pol_name)[0]
- if output_name is None:
- pol_name = os.path.split(policy_path)[1]
- output_name = os.path.splitext(pol_name)[0]
+
+ policy_tokens = policy_path.split('.')
+ pi = load_class_from_str('.'.join(policy_tokens[:-1]), policy_tokens[-1])
+
+ if pi is not None:
+ pi = pi(env, seed)
+ else:
+ pi = pickle.load(open(policy_path, 'rb'))
+ if output_dir == './': # overide the default
+ output_dir, pol_name = os.path.split(policy_path)
+ output_name = os.path.splitext(pol_name)[0]
+ if output_name is None:
+ pol_name = os.path.split(policy_path)[1]
+ output_name = os.path.splitext(pol_name)[0]
else:
pi = rand_policy(env, seed)
mode = 'exploration'
diff --git a/robohive/utils/inverse_kinematics.py b/robohive/utils/inverse_kinematics.py
index add3701b..21abd8eb 100644
--- a/robohive/utils/inverse_kinematics.py
+++ b/robohive/utils/inverse_kinematics.py
@@ -223,8 +223,9 @@ def qpos_from_site_pose(physics,
steps, err_norm, update_norm)
if not success and steps == max_steps - 1:
- logging.warning('Failed to converge after %i steps: err_norm=%3g',
- steps, err_norm)
+ #logging.warning('Failed to converge after %i steps: err_norm=%3g',
+ # steps, err_norm)
+ pass
if not inplace:
# Our temporary copy of physics.data is about to go out of scope, and when
diff --git a/robohive/utils/paths_utils.py b/robohive/utils/paths_utils.py
index 3e481e1c..2b88770e 100644
--- a/robohive/utils/paths_utils.py
+++ b/robohive/utils/paths_utils.py
@@ -86,19 +86,26 @@ def plot(paths, env=None, fileName_prefix=''):
plt.clf()
# observations
- nplt1 = len(path['env_infos']['obs_dict'].keys())
+ path_keys = path.keys()
+ env_info_keys = []
+ for k in path_keys:
+ print(k)
+ if 'env_infos/obs_dict' in k:
+ env_info_keys.append(k)
+
+ nplt1 = len(env_info_keys)
for iplt1, key in enumerate(
- sorted(path['env_infos']['obs_dict'].keys())):
+ sorted(env_info_keys)):
ax = plt.subplot(nplt1, 2, iplt1 * 2 + 1)
if iplt1 != (nplt1 - 1):
ax.axes.xaxis.set_ticklabels([])
if iplt1 == 0:
plt.title('Observations')
ax.yaxis.tick_right()
- if path['env_infos']['obs_dict'][key].ndim<3:
+ if path[key].ndim<3:
plt.plot(
- path['env_infos']['time'],
- path['env_infos']['obs_dict'][key],
+ path['env_infos/time'],
+ path[key],
label=key)
# plt.ylabel(key)
plt.text(0.01, .01, key, transform=ax.transAxes)
@@ -110,12 +117,13 @@ def plot(paths, env=None, fileName_prefix=''):
ax.set_prop_cycle(None)
# h4 = plt.plot(path['env_infos']['time'], env.env.act_mid + path['actions']*env.env.act_rng, '-', label='act') # plot scaled actions
h4 = plt.plot(
- path['env_infos']['time'], path['actions'], '-',
+ path['env_infos/time'], path['actions'], '-',
label='act') # plot normalized actions
plt.ylabel('actions')
ax.axes.xaxis.set_ticklabels([])
ax.yaxis.tick_right()
+ '''
# rewards/ scores
if "score" in path['env_infos']:
ax = plt.subplot(nplt2, 2, 6)
@@ -159,7 +167,7 @@ def plot(paths, env=None, fileName_prefix=''):
ax.axes.xaxis.set_ticklabels([])
plt.ylabel('wt*rewards')
ax.yaxis.tick_right()
-
+ '''
file_name = fileName_prefix + path_name + '.pdf'
plt.savefig(file_name)
print("saved ", file_name)
@@ -188,10 +196,10 @@ def render(rollout_path, render_format:str="mp4", cam_names:list=["left"]):
for i_path, path in enumerate(paths):
if output_type=='.h5':
- data = paths[path]['data']
+ data = paths[path]['env_infos/visual_dict']
path_horizon = data['time'].shape[0]
else:
- data = path['env_infos']['obs_dict']
+ data = path['env_infos/visual_dict']
path_horizon = path['env_infos']['time'].shape[0]
# find full key name
@@ -427,4 +435,4 @@ def util_path_cli(util, path, env, output_name, output_dir, verify_output, rende
if __name__ == '__main__':
- util_path_cli()
\ No newline at end of file
+ util_path_cli()
diff --git a/robohive/utils/prompt_utils.py b/robohive/utils/prompt_utils.py
index e7ffa0d5..c9068e62 100644
--- a/robohive/utils/prompt_utils.py
+++ b/robohive/utils/prompt_utils.py
@@ -9,7 +9,7 @@ class Prompt(enum.IntEnum):
NONE = 4
# Global verbose mode
-VERBOSE_MODE = Prompt.INFO
+VERBOSE_MODE = Prompt.ERROR
def set_prompt_verbosity(verbose_mode:Prompt=Prompt.INFO):
global VERBOSE_MODE