| |
| import os |
| import time |
| import numpy as np |
| import h5py |
| import argparse |
| import dm_env |
| import cv2 |
| import queue |
|
|
| import rospy |
| from sensor_msgs.msg import JointState |
| from sensor_msgs.msg import Image |
| from nav_msgs.msg import Odometry |
| from cv_bridge import CvBridge |
|
|
| import threading |
| import collections |
|
|
| import sys |
| sys.path.append("./") |
|
|
|
|
|
|
| |
| def save_data(args, timesteps, actions, dataset_path): |
| use_depth_image = args.use_depth_image |
| is_compress = args.is_compress |
| |
| |
| data_dict = { |
| |
| '/observations/qpos': [], |
| '/observations/qvel': [], |
| '/observations/effort': [], |
| '/action': [], |
| '/base_action': [], |
| } |
|
|
| |
| for cam_name in args.camera_names: |
| data_dict[f'/observations/images/{cam_name}'] = [] |
| if use_depth_image: |
| data_dict[f'/observations/depths/{cam_name}'] = [] |
| |
|
|
| |
| |
| while actions: |
| |
| action = actions.pop(0) |
| ts = timesteps.pop(0) |
|
|
| |
| |
| data_dict['/observations/qpos'].append(ts.observation['qpos']) |
| data_dict['/observations/qvel'].append(ts.observation['qvel']) |
| data_dict['/observations/effort'].append(ts.observation['effort']) |
|
|
| |
| data_dict['/action'].append(action) |
| data_dict['/base_action'].append(ts.observation['base_vel']) |
|
|
| |
| for cam_name in args.camera_names: |
| data_dict[f'/observations/images/{cam_name}'].append(ts.observation['images'][cam_name]) |
| |
| if use_depth_image: |
| data_dict[f'/observations/depths/{cam_name}'].append(ts.observation['depths'][cam_name]) |
|
|
| pass |
| if is_compress: |
| encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), 50] |
| compressed_len = [] |
| |
| for cam_name in args.camera_names: |
| image_list = data_dict[f'/observations/images/{cam_name}'] |
| compressed_list = [] |
| compressed_len.append([]) |
| |
| for image in image_list: |
| result, encoded_image = cv2.imencode('.jpg', image, encode_param) |
| |
| compressed_list.append(encoded_image) |
| compressed_len[-1].append(len(encoded_image)) |
| |
| |
| data_dict[f'/observations/images/{cam_name}'] = compressed_list |
|
|
| compressed_len = np.array(compressed_len) |
| padded_size = compressed_len.max() |
| |
| for cam_name in args.camera_names: |
| compressed_image_list = data_dict[f'/observations/images/{cam_name}'] |
| padded_compressed_image_list = [] |
| for compressed_image in compressed_image_list: |
| padded_compressed_image = np.zeros(padded_size, dtype='uint8') |
| image_len = len(compressed_image) |
| padded_compressed_image[:image_len] = compressed_image |
| padded_compressed_image_list.append(padded_compressed_image) |
| data_dict[f'/observations/images/{cam_name}'] = padded_compressed_image_list |
|
|
| |
| if use_depth_image: |
| compressed_len_depth = [] |
| |
| for cam_name in args.camera_names: |
| depth_list = data_dict[f'/observations/depths/{cam_name}'] |
| compressed_list_depth = [] |
| compressed_len_depth.append([]) |
| |
| for depth in depth_list: |
| result, encoded_depth = cv2.imencode('.jpg', depth, encode_param) |
| |
| compressed_list_depth.append(encoded_depth) |
| compressed_len_depth[-1].append(len(encoded_depth)) |
| |
| |
| data_dict[f'/observations/depths/{cam_name}'] = compressed_list_depth |
|
|
| compressed_len_depth = np.array(compressed_len_depth) |
| padded_size_depth = compressed_len_depth.max() |
| |
| for cam_name in args.camera_names: |
| compressed_depth_list = data_dict[f'/observations/depths/{cam_name}'] |
| padded_compressed_depth_list = [] |
| for compressed_depth in compressed_depth_list: |
| padded_compressed_depth = np.zeros(padded_size_depth, dtype='uint8') |
| depth_len = len(compressed_depth) |
| padded_compressed_depth[:depth_len] = compressed_depth |
| padded_compressed_depth_list.append(padded_compressed_depth) |
| data_dict[f'/observations/depths/{cam_name}'] = padded_compressed_depth_list |
|
|
|
|
|
|
|
|
| t0 = time.time() |
| with h5py.File(dataset_path + '.hdf5', 'w', rdcc_nbytes=1024**2*2) as root: |
| |
| |
| |
| |
| root.attrs['sim'] = False |
| root.attrs['compress'] = False |
| if args.is_compress: |
| root.attrs['compress'] = True |
|
|
| |
| |
| obs = root.create_group('observations') |
| |
| image = obs.create_group('images') |
|
|
| depth = obs.create_group('depths') |
|
|
| for cam_name in args.camera_names: |
| if args.is_compress: |
| _ = image.create_dataset(cam_name, (args.max_timesteps, padded_size), dtype='uint8', |
| chunks=(1, padded_size), ) |
| if use_depth_image: |
| |
| |
| _ = depth.create_dataset(cam_name, (args.max_timesteps, padded_size_depth), dtype='uint8', |
| chunks=(1, padded_size_depth), ) |
|
|
|
|
| else: |
| _ = image.create_dataset(cam_name, (args.max_timesteps, 480, 640, 3), dtype='uint8', |
| chunks=(1, 480, 640, 3), ) |
| if use_depth_image: |
| _ = depth.create_dataset(cam_name, (args.max_timesteps, 400, 640), dtype='uint8', |
| chunks=(1, 400, 640), ) |
|
|
| _ = obs.create_dataset('qpos', (args.max_timesteps, 14)) |
| _ = obs.create_dataset('qvel', (args.max_timesteps, 14)) |
| _ = obs.create_dataset('effort', (args.max_timesteps, 14)) |
| _ = root.create_dataset('action', (args.max_timesteps, 14)) |
| _ = root.create_dataset('base_action', (args.max_timesteps, 2)) |
|
|
|
|
| if is_compress: |
| _ = root.create_dataset('compress_len', (len(args.camera_names), args.max_timesteps)) |
| root['/compress_len'][...] = compressed_len |
|
|
| |
| |
| for name, array in data_dict.items(): |
| root[name][...] = array |
|
|
| print(f'Saving: {time.time() - t0:.1f} secs', dataset_path) |
|
|
|
|
| class RosOperator: |
| def __init__(self, args): |
| self.init(args) |
|
|
| def init(self, args): |
| self.args = args |
| self.use_depth_image = self.args.use_depth_image |
| self.use_robot_base = self.args.use_robot_base |
|
|
| self.bridge = CvBridge() |
| self.imgl_queue, self.imgr_queue, self.imgf_queue = [queue.Queue() for _ in range(3)] |
| self.depthl_queue, self.depthr_queue, self.depthf_queue = [queue.Queue() for _ in range(3)] |
| self.masterl_queue, self.masterr_queue, self.puppetl_queue, self.puppetr_queue = [queue.Queue() for _ in range(4)] |
| self.robot_base_deque = queue.Queue() |
|
|
| dataset_dir = os.path.join(args.dataset_dir, args.task_name) |
| if not os.path.exists(dataset_dir): |
| os.makedirs(dataset_dir) |
| self.dataset_path = os.path.join(dataset_dir, "episode_" + str(args.episode_idx)) |
|
|
| self.register_sub() |
|
|
| def register_sub(self): |
| rospy.init_node('record_episodes', anonymous=True) |
| |
| rospy.Subscriber(self.args.img_left_topic, Image, lambda msg: self.imgl_queue.put(msg), queue_size=60, tcp_nodelay=True) |
| rospy.Subscriber(self.args.img_right_topic, Image, lambda msg: self.imgr_queue.put(msg), queue_size=60, tcp_nodelay=True) |
| rospy.Subscriber(self.args.img_front_topic, Image, lambda msg: self.imgf_queue.put(msg), queue_size=60, tcp_nodelay=True) |
| |
| if self.use_depth_image: |
| rospy.Subscriber(self.args.depth_left_topic, Image, lambda msg: self.depthl_queue.put(msg), queue_size=60, tcp_nodelay=True) |
| rospy.Subscriber(self.args.depth_right_topic, Image, lambda msg: self.depthr_queue.put(msg), queue_size=60, tcp_nodelay=True) |
| rospy.Subscriber(self.args.depth_front_topic, Image, lambda msg: self.depthf_queue.put(msg), queue_size=60, tcp_nodelay=True) |
|
|
|
|
| rospy.Subscriber(self.args.master_arm_left_topic, JointState, lambda msg: self.masterl_queue.put(msg), queue_size=200, tcp_nodelay=True) |
| rospy.Subscriber(self.args.master_arm_right_topic, JointState, lambda msg: self.masterr_queue.put(msg), queue_size=200, tcp_nodelay=True) |
| rospy.Subscriber(self.args.puppet_arm_left_topic, JointState, lambda msg: self.puppetl_queue.put(msg), queue_size=200, tcp_nodelay=True) |
| rospy.Subscriber(self.args.puppet_arm_right_topic, JointState, lambda msg: self.puppetr_queue.put(msg), queue_size=200, tcp_nodelay=True) |
| |
| if self.use_robot_base: |
| rospy.Subscriber(self.args.robot_base_topic, Odometry, lambda msg: self.robot_base_deque.put(msg), queue_size=60, tcp_nodelay=True) |
|
|
| |
| def collet_data(self): |
| rate = rospy.Rate(30) |
| input("\033[32m\nPlease press any key to continue\n\033[0m") |
| |
| count = 0 |
| timesteps = [] |
| actions = [] |
| |
| |
| while (count < self.args.max_timesteps + 1 and not rospy.is_shutdown()): |
| time1 = time.time() |
| |
| if self.imgl_queue.empty() or self.imgr_queue.empty() or self.imgf_queue.empty() or \ |
| (self.use_depth_image and (self.depthl_queue.empty() or self.depthr_queue.empty() or self.depthf_queue.empty())): |
| print("\033[31mPlease check topic\n\033[0m") |
| rate.sleep() |
| continue |
| |
| if self.masterl_queue.empty() or self.masterr_queue.empty() or \ |
| self.puppetl_queue.empty() or self.puppetr_queue.empty() or \ |
| ( self.use_robot_base and ( self.robot_base_deque.empty() ) ): |
| print("\033[31mPlease check topic\n\033[0m") |
| rate.sleep() |
| continue |
| |
| imgl, imgr, imgl, depthl, depthr, depthl = [None for _ in range(6)] |
| masterl, masterr, puppetl, puppetr = [None for _ in range(4)] |
| robot_base = None |
|
|
| min_timestamps = min(self.imgl_queue.queue[-1].header.stamp.to_sec(), |
| self.imgr_queue.queue[-1].header.stamp.to_sec(), |
| self.imgf_queue.queue[-1].header.stamp.to_sec()) - 0.01 |
| |
| if(self.use_depth_image): |
| min_timestamps = min(min_timestamps, |
| self.depthl_queue.queue[-1].header.stamp.to_sec(), |
| self.depthr_queue.queue[-1].header.stamp.to_sec(), |
| self.depthf_queue.queue[-1].header.stamp.to_sec(), |
| ) - 0.01 |
|
|
| while (self.imgl_queue.queue[0].header.stamp.to_sec() < min_timestamps): |
| self.imgl_queue.get() |
| imgl = self.bridge.imgmsg_to_cv2(self.imgl_queue.get(), 'passthrough') |
|
|
| while (self.imgr_queue.queue[0].header.stamp.to_sec() < min_timestamps): |
| self.imgr_queue.get() |
| imgr = self.bridge.imgmsg_to_cv2(self.imgr_queue.get(), 'passthrough') |
|
|
| while (self.imgf_queue.queue[0].header.stamp.to_sec() < min_timestamps): |
| self.imgf_queue.get() |
| imgf = self.bridge.imgmsg_to_cv2(self.imgf_queue.get(), 'passthrough') |
| |
| if(self.use_depth_image): |
| while (self.depthl_queue.queue[0].header.stamp.to_sec() < min_timestamps): |
| self.depthl_queue.get() |
| depthl = self.bridge.imgmsg_to_cv2(self.depthl_queue.get(), 'passthrough') |
|
|
| while (self.depthr_queue.queue[0].header.stamp.to_sec() < min_timestamps): |
| self.depthr_queue.get() |
| depthr = self.bridge.imgmsg_to_cv2(self.depthr_queue.get(), 'passthrough') |
|
|
| while (self.depthf_queue.queue[0].header.stamp.to_sec() < min_timestamps): |
| self.depthf_queue.get() |
| depthf = self.bridge.imgmsg_to_cv2(self.depthf_queue.get(), 'passthrough') |
| |
|
|
|
|
| while (self.masterl_queue.queue[0].header.stamp.to_sec() < min_timestamps): |
| self.masterl_queue.get() |
| masterl = self.masterl_queue.get() |
|
|
| while (self.masterr_queue.queue[0].header.stamp.to_sec() < min_timestamps): |
| self.masterr_queue.get() |
| masterr = self.masterr_queue.get() |
|
|
| while (self.puppetl_queue.queue[0].header.stamp.to_sec() < min_timestamps): |
| self.puppetl_queue.get() |
| puppetl = self.puppetl_queue.get() |
|
|
| while (self.puppetr_queue.queue[0].header.stamp.to_sec() < min_timestamps): |
| self.puppetr_queue.get() |
| puppetr = self.puppetl_queue.get() |
|
|
| if(self.use_robot_base): |
| while self.robot_base_deque[0].header.stamp.to_sec() < min_timestamps: |
| self.robot_base_deque.get() |
| robot_base = self.robot_base_deque.get() |
|
|
| |
| |
| |
| |
|
|
| count += 1 |
| |
|
|
| |
| image_dict = dict() |
| image_dict[self.args.camera_names[0]] = imgf |
| image_dict[self.args.camera_names[1]] = imgl |
| image_dict[self.args.camera_names[2]] = imgr |
|
|
| |
| obs = collections.OrderedDict() |
| obs['images'] = image_dict |
| obs['qpos'] = np.concatenate((np.array(puppetl.position), np.array(puppetr.position)), axis=0) |
| obs['qvel'] = np.concatenate((np.array(puppetl.velocity), np.array(puppetr.velocity)), axis=0) |
| obs['effort'] = np.concatenate((np.array(puppetl.effort), np.array(puppetr.effort)), axis=0) |
| |
| |
| if self.use_robot_base: |
| obs['base_vel'] = [robot_base.twist.twist.linear.x, robot_base.twist.twist.angular.z] |
| else: |
| obs['base_vel'] = [0.0, 0.0] |
|
|
| |
| if(self.use_depth_image): |
| depth_dict = dict() |
| depth_dict[self.args.camera_names[0]] = depthf |
| depth_dict[self.args.camera_names[1]] = depthl |
| depth_dict[self.args.camera_names[2]] = depthr |
| obs['depths'] = depth_dict |
|
|
| |
| if count == 1: |
| ts = dm_env.TimeStep( |
| step_type=dm_env.StepType.FIRST, |
| reward=None, |
| discount=None, |
| observation=obs) |
| |
| timesteps.append(ts) |
| print("frame %s cost_time: %s" % (count, round(1/(time.time() - time1), 6))) |
| rate.sleep() |
| continue |
|
|
| |
| ts = dm_env.TimeStep( |
| step_type=dm_env.StepType.MID, |
| reward=None, |
| discount=None, |
| observation=obs) |
|
|
| |
| action = np.concatenate((np.array(masterl.position), np.array(masterr.position)), axis=0) |
| actions.append(action) |
| timesteps.append(ts) |
|
|
| if rospy.is_shutdown(): |
| exit(-1) |
| |
| print("frame %s cost_time: %s" % (count, round((time.time() - time1), 6))) |
| rate.sleep() |
| |
| print("len(timesteps): ", len(timesteps)) |
| print("len(actions) : ", len(actions)) |
| save_data(self.args, timesteps, actions, self.dataset_path) |
|
|
| def get_arguments(): |
| parser = argparse.ArgumentParser() |
| parser.add_argument('--dataset_dir', action='store', type=str, help='Dataset_dir.', |
| default="./data", required=False) |
| |
| parser.add_argument('--task_name', action='store', type=str, help='Task name.', |
| default="aloha_mobile_dummy", required=False) |
| |
| parser.add_argument('--episode_idx', action='store', type=int, help='Episode index.', |
| default=0, required=False) |
| parser.add_argument('--max_timesteps', action='store', type=int, help='Max_timesteps.', |
| default=500, required=False) |
|
|
| |
| parser.add_argument('--camera_names', action='store', type=str, help='camera_names', |
| default=['cam_high', 'cam_left_wrist', 'cam_right_wrist'], required=False) |
| |
| |
| parser.add_argument('--img_front_topic', action='store', type=str, help='img_front_topic', |
| default='/camera_f/color/image_raw', required=False) |
| parser.add_argument('--img_left_topic', action='store', type=str, help='img_left_topic', |
| default='/camera_l/color/image_raw', required=False) |
| parser.add_argument('--img_right_topic', action='store', type=str, help='img_right_topic', |
| default='/camera_r/color/image_raw', required=False) |
| |
| |
| parser.add_argument('--use_depth_image', action='store_true', help='--use_depth_image', required=False) |
| |
| parser.add_argument('--depth_front_topic', action='store', type=str, help='depth_front_topic', |
| default='/camera_f/depth/image_raw', required=False) |
| parser.add_argument('--depth_left_topic', action='store', type=str, help='depth_left_topic', |
| default='/camera_l/depth/image_raw', required=False) |
| parser.add_argument('--depth_right_topic', action='store', type=str, help='depth_right_topic', |
| default='/camera_r/depth/image_raw', required=False) |
|
|
| |
| parser.add_argument('--master_arm_left_topic', action='store', type=str, help='master_arm_left_topic', |
| default='/master/joint_left', required=False) |
| parser.add_argument('--master_arm_right_topic', action='store', type=str, help='master_arm_right_topic', |
| default='/master/joint_right', required=False) |
| |
| parser.add_argument('--puppet_arm_left_topic', action='store', type=str, help='puppet_arm_left_topic', |
| default='/puppet/joint_left', required=False) |
| parser.add_argument('--puppet_arm_right_topic', action='store', type=str, help='puppet_arm_right_topic', |
| default='/puppet/joint_right', required=False) |
| |
| parser.add_argument('--use_robot_base', action='store', type=bool, help='use_robot_base', |
| default=False, required=False) |
| parser.add_argument('--robot_base_topic', action='store', type=str, help='robot_base_topic', |
| default='/odom_raw', required=False) |
| |
| |
| parser.add_argument('--frame_rate', action='store', type=int, help='frame_rate', |
| default=30, required=False) |
| |
| |
| parser.add_argument('--is_compress', action='store_true', help='is_compress', required=False) |
| |
| args = parser.parse_args() |
| return args |
|
|
|
|
| def main(): |
| args = get_arguments() |
| ros_operator = RosOperator(args) |
|
|
| t1 = threading.Thread(target=ros_operator.collet_data) |
| t1.start() |
| t1.join() |
| |
|
|
| if __name__ == '__main__': |
| main() |
|
|
| |
|
|