Example #1
0
 def test_matrix_representation(self):
     ref_motion = bvh.load(file=TEST_SINUSOIDAL_FILE)
     test_motion = bvh.load(
         file=TEST_SINUSOIDAL_FILE,
         load_motion=False,
     )
     ref_matrix = ref_motion.to_matrix()
     test_motion = motion_class.Motion.from_matrix(
         ref_matrix,
         ref_motion.skel,
     )
     self.assert_motion_equal(ref_motion, test_motion)
Example #2
0
 def test_load_motion(self):
     # Load file
     motion = asfamc.load(file="tests/data/01.asf",
                          motion="tests/data/01_01.amc")
     motion_bvh = bvh.load(file="tests/data/01_01.bvh")
     for i in range(1, motion.num_frames()):
         pose = motion.get_pose_by_frame(i)
         pose_bvh = motion_bvh.get_pose_by_frame(i)
         """
         for k, j in zip(pose.skel.joints, pose_bvh.skel.joints):
             print(k.name, j.name)
         root Hips
         lhipjoint LHipJoint
         lfemur LeftUpLeg
         ltibia LeftLeg
         lfoot LeftFoot
         ltoes LeftToeBase
         rhipjoint RHipJoint
         rfemur RightUpLeg
         rtibia RightLeg
         rfoot RightFoot
         rtoes RightToeBase
         lowerback LowerBack
         upperback Spine
         thorax Spine1
         lowerneck Neck
         upperneck Neck1
         head Head
         lclavicle LeftShoulder
         lhumerus LeftArm
         lradius LeftForeArm
         lwrist LeftHand
         lhand LeftFingerBase
         lfingers LFingers
         lthumb LThumb
         rclavicle RightShoulder
         rhumerus RightArm
         rradius RightForeArm
         rwrist RightHand
         rhand RightFingerBase
         rfingers RFingers
         rthumb RThumb
         """
         for joint_idx, (k, j) in enumerate(zip(pose.data, pose_bvh.data)):
             # As asfamc and bvh are from different sources, we are not strictly comparing them.
             # We require no more than two different elements.
             failures = 0
             if joint_idx == 0:
                 compare_rotation = 0
             else:
                 compare_rotation = 1
             for kk, jj in zip(
                     np.nditer(k[:, :3 - compare_rotation]),
                     np.nditer(j[:, :3 - compare_rotation]),
             ):
                 if abs(kk - jj) > 0.2:
                     failures += 1
             assert failures <= 2, failures
Example #3
0
def split_bvh(filepath, time_window, output_folder):
    motion = bvh.load(filepath)
    frames_per_time_window = time_window * motion.fps
    for num, i in enumerate(
            range(0, motion.num_frames(), int(frames_per_time_window / 2))):
        motion_slice = motion_ops.cut(motion, i, i + frames_per_time_window)
        filepath_slice = os.path.join(
            output_folder,
            filepath.split(".")[-2].split("/")[-1] + "_" + str(num) + ".bvh",
        )
        bvh.save(motion_slice, filepath_slice)
Example #4
0
 def __init__(self, root_folder, percentile=95, sliding_window=2):
     self.percentile = percentile
     self.velocities = defaultdict(list)
     self.sliding_window = sliding_window
     for root, _, files in os.walk(root_folder, topdown=False):
         for filename in tqdm.tqdm(files):
             motion = bvh.load(os.path.join(root, filename))
             self.joints = [joint.name for joint in motion.skel.joints]
             self._update_velocities(
                 motion.positions(local=False),
                 1 / motion.fps,
             )
     self.thresholds = self._compute_p95_thresholds()
Example #5
0
 def test_motion(self):
     motion = bvh.load(file=TEST_SINUSOIDAL_FILE)
     # Inspect 0th frame, root joint
     T = motion.get_pose_by_frame(0).get_transform(0, local=False)
     _, p = conversions.T2Rp(T)
     self.assertListEqual(list(p), [-3, 6, 5])
     # Inspect 100th frame, root joint
     T = motion.get_pose_by_frame(100).get_transform(0, local=False)
     _, p = conversions.T2Rp(T)
     self.assertListEqual(list(p), [-3, 6, 5])
     # Inspect 100th frame, "child2" joint
     T = motion.get_pose_by_frame(100).get_transform("child2", local=False)
     _, p = conversions.T2Rp(T)
     self.assertListEqual(list(p), [-8, 11, 5])
Example #6
0
    def test_append_motion(self):
        motion1 = bvh.load(file="tests/data/sinusoidal.bvh")
        motion2 = bvh.load(file="tests/data/sinusoidal.bvh")
        num_frames = motion1.num_frames()

        # Append motion 1 and motion 2, and check total combined frames
        combined_motion1 = motion_ops.append(motion1, motion2)
        self.assertEqual(
            combined_motion1.num_frames(),
            motion1.num_frames() + motion2.num_frames(),
        )

        # Append motion 1 and motion 3, and check total combined frames
        motion3 = bvh.load(file="tests/data/sinusoidal.bvh")
        combined_motion2 = motion_ops.append(motion1, motion3)
        self.assertEqual(
            combined_motion2.num_frames(),
            motion1.num_frames() + motion3.num_frames(),
        )
        # Ensure operation has not been done in place
        self.assertEqual(
            motion1.num_frames(),
            num_frames,
        )

        # Test blending
        blend_length = 0.1
        combined_motion3 = motion_ops.append_and_blend(
            motion1,
            motion2,
            blend_length=blend_length,
        )
        self.assertEqual(
            combined_motion3.num_frames(),
            (motion1.num_frames() + motion2.num_frames() -
             blend_length * motion1.fps),
        )
Example #7
0
 def load_motion_at_idx(self, idx, file):
     motion = velocity.MotionWithVelocity(skel=self.skel)
     motion = bvh.load(
         file=file,
         motion=motion,
         scale=self.scale,
         load_skel=self.skel is None,
         v_up_skel=self.skel.v_up,
         v_face_skel=self.skel.v_face,
         v_up_env=self.skel.v_up_env,
     )
     motion.resample(fps=self.fps)
     self.motions[idx] = motion
     if self.verbose:
         logging.info(f"Loaded: {file}")
Example #8
0
def main(args):
    motion = bvh.load(args.input_file)
    trajectory = motion.positions(local=False).reshape(motion.num_frames(), -1)
    print("Total length (in s) ", motion.length())

    # Assumes you have a trajectory that has axis 0 as time and axis 1 as
    # state dimensions.
    acc = np.diff(trajectory, n=2, axis=0)
    acc_norm = np.linalg.norm(acc, axis=1)
    segs = find_peaks(acc_norm, height=0.075)[0]
    # sega = argrelextrema(acc_norm, np.greater, order=8)[0]

    print("Number of detected segments ", len(segs))

    if args.output_plot is not None:
        plot_changepoints(acc_norm, segs, args.output_plot)
Example #9
0
    def test_load_motion(self):
        # Load file
        motion = bvh.load(file=TEST_SINUSOIDAL_FILE)

        # Read pose data from all frames (in Euler angle)
        with open(TEST_SINUSOIDAL_FILE) as f:
            file_content = f.readlines()
        for frame_num, line in enumerate(file_content[-motion.num_frames():]):
            # Skip first 3 entries that store translation data, and read the
            # Euler angle data of joints
            angle_data = np.array(list(map(float,
                                           line.strip().split()))[3:]).reshape(
                                               -1, 3)
            for T, true_E in zip(motion.poses[frame_num].data, angle_data):
                R, _ = conversions.T2Rp(T)
                E = conversions.R2E(R, order="XYZ", degrees=True)
                np.testing.assert_almost_equal(E, true_E)
Example #10
0
    def test_save_motion(self):
        # Load file
        motion = bvh.load(file=TEST_SINUSOIDAL_FILE)

        with tempfile.NamedTemporaryFile() as fp:
            # Save loaded file
            bvh.save(motion, fp.name, rot_order="XYZ")
            # Reload saved file and test if it is same as reference file
            # Read pose data from all frames (in Euler angle)
            with open(TEST_SINUSOIDAL_FILE) as f:
                orig_file = f.readlines()
            with open(fp.name) as f:
                saved_file = f.readlines()
            for orig_line, saved_line in zip(
                    orig_file[-motion.num_frames():],
                    saved_file[-motion.num_frames():],
            ):
                # Skip first 3 entries that store translation data, and read
                # the Euler angle data of joints
                orig_data, saved_data = [
                    np.array(list(map(float,
                                      line.strip().split())))
                    for line in [orig_line, saved_line]
                ]
                np.testing.assert_almost_equal(orig_data, saved_data)

            # Reload saved file and test if it has the same data as original
            # motion object
            with open(TEST_SINUSOIDAL_FILE) as f:
                file_content = f.readlines()
            for frame_num, line in enumerate(
                    file_content[-motion.num_frames():]):
                # Skip first 3 entries that store translation data, and read
                # the Euler angle data of joints
                angle_data = np.array(
                    list(map(float,
                             line.strip().split()))[3:]).reshape(-1, 3)
                for T, true_E in zip(motion.poses[frame_num].data, angle_data):
                    R, _ = conversions.T2Rp(T)
                    E = conversions.R2E(R, order="XYZ", degrees=True)
                    np.testing.assert_almost_equal(E, true_E)
def load_motions(motion_files, skel, char_info, verbose):
    assert motion_files is not None
    motion_file_names = []
    for names in motion_files:
        head, tail = os.path.split(names)
        motion_file_names.append(tail)
    if isinstance(motion_files[0], str):
        motion_dict = {}
        motion_all = []
        for i, file in enumerate(motion_files):
            ''' If the same file is already loaded, do not load again for efficiency'''
            if file in motion_dict:
                m = motion_dict[file]
            else:
                if file.endswith('bvh'):
                    m = bvh.load(motion=Motion(name=file, skel=skel),
                                 file=file,
                                 scale=1.0,
                                 load_skel=False,
                                 v_up_skel=char_info.v_up,
                                 v_face_skel=char_info.v_face,
                                 v_up_env=char_info.v_up_env)
                    m = MotionWithVelocity.from_motion(m)
                elif file.endswith('bin'):
                    m = pickle.load(open(file, "rb"))
                elif file.endswith('gzip') or file.endswith('gz'):
                    with gzip.open(file, "rb") as f:
                        m = pickle.load(f)
                else:
                    raise Exception('Unknown Motion File Type')
                if verbose:
                    print('Loaded: %s' % file)
            motion_all.append(m)
    elif isinstance(motion_files[0], MotionWithVelocity):
        motion_all = motion_files
    else:
        raise Exception('Unknown Type for Reference Motion')

    return motion_all, motion_file_names
Example #12
0
def main(args):
    v_up_env = utils.str_to_axis(args.axis_up)
    if args.bvh_files:
        motions = [
            bvh.load(
                file=filename,
                v_up_skel=v_up_env,
                v_face_skel=utils.str_to_axis(args.axis_face),
                v_up_env=v_up_env,
                scale=args.scale,
            )
            for filename in args.bvh_files
        ]
    else:
        motions = [
            asfamc.load(file=f, motion=m)
            for f, m in zip(args.asf_files, args.amc_files)
        ]

    for i in range(len(motions)):
        motion_ops.translate(motions[i], [args.x_offset * i, 0, 0])
    cam = camera.Camera(
        pos=np.array(args.camera_position),
        origin=np.array(args.camera_origin),
        vup=v_up_env,
        fov=45.0,
    )
    viewer = MocapViewer(
        motions=motions,
        play_speed=args.speed,
        scale=args.scale,
        thickness=args.thickness,
        render_overlay=args.render_overlay,
        hide_origin=args.hide_origin,
        title="Motion Graph Viewer",
        cam=cam,
        size=(1280, 720),
    )
    viewer.run()
Example #13
0
    def __init__(self, config):
        project_dir = config['project_dir']
        char_info_module = config['character'].get('char_info_module')
        sim_char_file = config['character'].get('sim_char_file')
        base_motion_file = config['character'].get('base_motion_file')
        ref_motion_scale = config['character'].get('ref_motion_scale')
        environment_file = config['character'].get('environment_file')
        ref_motion_file = config['character'].get('ref_motion_file')
        self_collision = config['character'].get('self_collision')
        actuation = config['character'].get('actuation')
        ''' Append project_dir to the given file path '''

        if project_dir:
            for i in range(len(char_info_module)):
                char_info_module[i] = os.path.join(project_dir,
                                                   char_info_module[i])
                sim_char_file[i] = os.path.join(project_dir, sim_char_file[i])
                base_motion_file[i] = os.path.join(project_dir,
                                                   base_motion_file[i])
            if environment_file is not None:
                for i in range(len(environment_file)):
                    environment_file[i] = os.path.join(project_dir,
                                                       environment_file[i])
        ''' Create a base tracking environment '''

        self._base_env = env_humanoid_tracking.Env(
            fps_sim=config['fps_sim'],
            fps_act=config['fps_con'],
            verbose=config['verbose'],
            char_info_module=char_info_module,
            sim_char_file=sim_char_file,
            ref_motion_scale=ref_motion_scale,
            self_collision=self_collision,
            contactable_body=config['early_term'].get(
                'falldown_contactable_body'),
            actuation=actuation,
        )

        self._pb_client = self._base_env._pb_client
        self._dt_con = 1.0 / config['fps_con']
        ''' Copy some of frequently used attributes from the base environemnt '''
        self._num_agent = self._base_env._num_agent
        assert self._num_agent == len(base_motion_file)
        self._sim_agent = [
            self._base_env._agent[i] for i in range(self._num_agent)
        ]
        self._v_up = self._base_env._v_up
        ''' State '''
        self._state_choices = [
            Env.StateChoice.from_string(s) for s in config['state']['choices']
        ]
        ''' Early Terminations '''
        self._early_term_choices = [
            Env.EarlyTermChoice.from_string(s)
            for s in config['early_term']['choices']
        ]

        self._reward_fn_def = config['reward']['fn_def']
        self._reward_fn_map = config['reward']['fn_map']
        self._reward_names = [
            self.get_reward_names(self._reward_fn_def[self._reward_fn_map[i]])
            for i in range(self._num_agent)
        ]
        '''
        Check the existence of reward definitions, which are defined in our reward map
        '''
        assert len(self._reward_fn_map) == self._num_agent
        for key in self._reward_fn_map:
            assert key in self._reward_fn_def.keys()

        self._verbose = config['verbose']

        if Env.EarlyTermChoice.LowReward in self._early_term_choices:
            self._et_low_reward_thres = config['early_term'][
                'low_reward_thres']
            self._rew_queue = self._num_agent * [None]
            for i in range(self._num_agent):
                self._rew_queue[i] = deque(maxlen=int(1.0 / self._dt_con))
        ''' The environment automatically terminates after 'sim_window' seconds '''
        if Env.EarlyTermChoice.SimWindow in self._early_term_choices:
            self._sim_window_time = config['early_term']['sim_window_time']
        ''' 
        The environment continues for "eoe_margin" seconds after end-of-episode is set by TRUE.
        This is useful for making the controller work for boundaries of reference motions
        '''
        self._eoe_margin = config['early_term']['eoe_margin']

        self._action_type = Env.ActionMode.from_string(
            config['action']['type'])
        ''' Base motion defines the initial posture (like t-pose) '''

        self._base_motion = []
        for i in range(self._num_agent):
            m = bvh.load(file=base_motion_file[i],
                         motion=MotionWithVelocity(),
                         scale=1.0,
                         load_skel=True,
                         load_motion=True,
                         v_up_skel=self._sim_agent[i]._char_info.v_up,
                         v_face_skel=self._sim_agent[i]._char_info.v_face,
                         v_up_env=self._sim_agent[i]._char_info.v_up_env)
            m = MotionWithVelocity.from_motion(m)
            self._base_motion.append(m)
        ''' Create Kinematic Agents '''

        self._kin_agent = []
        for i in range(self._num_agent):
            self._kin_agent.append(
                sim_agent.SimAgent(pybullet_client=self._base_env._pb_client,
                                   model_file=sim_char_file[i],
                                   char_info=self._sim_agent[i]._char_info,
                                   ref_scale=ref_motion_scale[i],
                                   self_collision=self_collision[i],
                                   kinematic_only=True,
                                   verbose=config['verbose']))
        ''' 
        Define the action space of this environment.
        Here I used a 'normalizer' where 'real' values correspond to joint angles,
        and 'norm' values correspond to the output value of NN policy.
        The reason why it is used is that NN policy somtimes could output values that
        are within much larger or narrow range than we need for the environment.
        For example, if we apply tanh activation function at the last layer of NN,
        the output are always within (-1, 1), but we need bigger values for joint angles 
        because 1 corresponds only to 57.3 degree.
        '''

        self._action_space = []
        for i in range(self._num_agent):
            dim = self._sim_agent[i].get_num_dofs()
            normalizer = math.Normalizer(
                real_val_max=config['action']['range_max'] * np.ones(dim),
                real_val_min=config['action']['range_min'] * np.ones(dim),
                norm_val_max=config['action']['range_max_pol'] * np.ones(dim),
                norm_val_min=config['action']['range_min_pol'] * np.ones(dim),
                apply_clamp=True)
            self._action_space.append(normalizer)

        self._com_vel = self._num_agent * [None]
        for i in range(self._num_agent):
            self._com_vel[i] = deque(maxlen=int(1.0 / self._dt_con))
        ''' 
        Any necessary information needed for training this environment.
        This can be set by calling "set_learning_info". 
        '''
        self._learning_info = {}

        self.add_noise = config['add_noise']
def extract_features(filepath, feature_type, thresholds=None, up_vec="z"):
    motion = bvh.load(filepath)
    if feature_type == "manual":
        return extract_manual_features(motion)
    else:
        return extract_kinetic_features(motion, thresholds, up_vec)
Example #15
0
 def test_cut_motion(self):
     motion = bvh.load(file="tests/data/sinusoidal.bvh")
     # Inspect 0th frame, root joint
     cut_motion = motion_ops.cut(motion, 3, 5)
     self.assertEqual(cut_motion.num_frames(), 2)
Example #16
0
def main(args):
    comp_device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    bm = BodyModel(model_type="smplh",
                   bm_path=args.body_model_file,
                   num_betas=10).to(comp_device)
    faces = c2c(bm.f)

    img_shape = (1600, 1600)
    motion = bvh.load(
        file=args.input_file,
        scale=0.5,
        v_up_skel=np.array([0.0, 1.0, 0.0]),
        v_face_skel=np.array([0.0, 0.0, 1.0]),
        v_up_env=np.array([0.0, 0.0, 1.0]),
    )
    motion = motion_ops.rotate(
        motion,
        conversions.Ax2R(conversions.deg2rad(-90)),
    )
    mv = prepare_mesh_viewer(img_shape)

    out = cv2.VideoWriter(args.video_output_file,
                          cv2.VideoWriter_fourcc(*"XVID"), 30, img_shape)

    parents = bm.kintree_table[0].long()[:21 + 1]
    parents = parents.cpu().numpy()
    dfs_order = get_dfs_order(parents)
    for frame in tqdm.tqdm(range(motion.num_frames())):
        pose = motion.get_pose_by_frame(frame)
        R, p = conversions.T2Rp(pose.data[0])
        root_orient = conversions.R2A(R)
        trans = p

        num_joints = len(pose.data) - 1
        body_model_pose_data = np.zeros(num_joints * 3)
        for motion_joint, amass_joint in enumerate(dfs_order):
            # motion_joint is idx of joint in Motion class order
            # amass_joint is idx of joint in AMASS skeleton
            if amass_joint == 0:
                continue
            pose_idx = amass_joint - 1
            # Convert rotation matrix to axis angle
            axis_angles = conversions.R2A(
                conversions.T2R(pose.data[motion_joint]))
            body_model_pose_data[pose_idx * 3:pose_idx * 3 + 3] = axis_angles

        pose_data_t = (
            torch.Tensor(body_model_pose_data).to(comp_device).unsqueeze(0))
        root_orient_t = torch.Tensor(root_orient).to(comp_device).unsqueeze(0)
        trans_t = torch.Tensor(trans).to(comp_device).unsqueeze(0)
        body = bm(pose_body=pose_data_t,
                  root_orient=root_orient_t,
                  trans=trans_t)

        body_mesh = trimesh.Trimesh(
            vertices=c2c(body.v[0]),
            faces=faces,
            vertex_colors=np.tile(colors["grey"], (6890, 1)),
        )
        # TODO: Add floor trimesh to the scene to display the ground plane
        mv.set_static_meshes([body_mesh])
        body_image = mv.render()
        img = body_image.astype(np.uint8)
        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        out.write(img)
    out.release()