Пример #1
0
    def _to_expmap(self, X):
        '''Converts Euler angles to Exponential Maps'''

        Q = []
        for track in X:
            channels = []
            titles = []
            euler_df = track.values

            # Create a new DataFrame to store the exponential map rep
            exp_df = pd.DataFrame(index=euler_df.index)

            # Copy the root positions into the new DataFrame
            rxp = '%s_Xposition' % track.root_name
            ryp = '%s_Yposition' % track.root_name
            rzp = '%s_Zposition' % track.root_name
            exp_df[rxp] = pd.Series(data=euler_df[rxp], index=exp_df.index)
            exp_df[ryp] = pd.Series(data=euler_df[ryp], index=exp_df.index)
            exp_df[rzp] = pd.Series(data=euler_df[rzp], index=exp_df.index)

            # List the columns that contain rotation channels
            rots = [
                c for c in euler_df.columns
                if ('rotation' in c and 'Nub' not in c)
            ]

            # List the joints that are not end sites, i.e., have channels
            joints = (joint for joint in track.skeleton if 'Nub' not in joint)

            for joint in joints:
                r = euler_df[[c for c in rots if joint in c
                              ]]  # Get the columns that belong to this joint
                euler = [[
                    f[1]['%s_Xrotation' % joint], f[1]['%s_Yrotation' % joint],
                    f[1]['%s_Zrotation' % joint]
                ] for f in r.iterrows()
                         ]  # Make sure the columsn are organized in xyz order
                exps = [
                    Rotation(f, 'euler', from_deg=True).to_expmap()
                    for f in euler
                ]  # Convert the eulers to exp maps

                # Create the corresponding columns in the new DataFrame

                exp_df['%s_alpha' % joint] = pd.Series(
                    data=[e[0] for e in exps], index=exp_df.index)
                exp_df['%s_beta' % joint] = pd.Series(
                    data=[e[1] for e in exps], index=exp_df.index)
                exp_df['%s_gamma' % joint] = pd.Series(
                    data=[e[2] for e in exps], index=exp_df.index)

            new_track = track.clone()
            new_track.values = exp_df
            Q.append(new_track)

        return Q
Пример #2
0
    def _to_pos(self, X):
        '''Converts joints rotations in Euler angles to joint positions'''

        Q = []
        for track in X:
            channels = []
            titles = []
            euler_df = track.values

            # Create a new DataFrame to store the exponential map rep
            pos_df = pd.DataFrame(index=euler_df.index)

            # Copy the root rotations into the new DataFrame
            # rxp = '%s_Xrotation'%track.root_name
            # ryp = '%s_Yrotation'%track.root_name
            # rzp = '%s_Zrotation'%track.root_name
            # pos_df[rxp] = pd.Series(data=euler_df[rxp], index=pos_df.index)
            # pos_df[ryp] = pd.Series(data=euler_df[ryp], index=pos_df.index)
            # pos_df[rzp] = pd.Series(data=euler_df[rzp], index=pos_df.index)

            # List the columns that contain rotation channels
            rot_cols = [c for c in euler_df.columns if ('rotation' in c)]

            # List the columns that contain position channels
            pos_cols = [c for c in euler_df.columns if ('position' in c)]

            # List the joints that are not end sites, i.e., have channels
            joints = (joint for joint in track.skeleton)

            tree_data = {}

            for joint in track.traverse():
                parent = track.skeleton[joint]['parent']

                # Get the rotation columns that belong to this joint
                rc = euler_df[[c for c in rot_cols if joint in c]]

                # Get the position columns that belong to this joint
                pc = euler_df[[c for c in pos_cols if joint in c]]

                # Make sure the columns are organized in xyz order
                if rc.shape[1] < 3:
                    euler_values = [[0, 0, 0] for f in rc.iterrows()]
                else:
                    euler_values = [[
                        f[1]['%s_Xrotation' % joint],
                        f[1]['%s_Yrotation' % joint],
                        f[1]['%s_Zrotation' % joint]
                    ] for f in rc.iterrows()]

                    ################# in euler angle, the order of rotation axis is very important #####################
                    rotation_order = rc.columns[0][rc.columns[0].find(
                        'rotation'
                    ) - 1] + rc.columns[1][
                        rc.columns[1].find('rotation') - 1] + rc.columns[2][
                            rc.columns[2].find('rotation') -
                            1]  #rotation_order is string : 'XYZ' or'ZYX' or ...
                    ####################################################################################################

                if pc.shape[1] < 3:
                    pos_values = [[0, 0, 0] for f in pc.iterrows()]
                else:
                    pos_values = [[
                        f[1]['%s_Xposition' % joint],
                        f[1]['%s_Yposition' % joint],
                        f[1]['%s_Zposition' % joint]
                    ] for f in pc.iterrows()]

                #euler_values = [[0,0,0] for f in rc.iterrows()] #for deugging
                #pos_values = [[0,0,0] for f in pc.iterrows()] #for deugging

                # Convert the eulers to rotation matrices
                ############################ input rotation order as Rotation class's argument #########################
                rotmats = np.asarray([
                    Rotation([f[0], f[1], f[2]],
                             'euler',
                             rotation_order,
                             from_deg=True).rotmat for f in euler_values
                ])
                ########################################################################################################
                tree_data[joint] = [
                    [],  # to store the rotation matrix
                    []  # to store the calculated position
                ]

                if track.root_name == joint:
                    tree_data[joint][0] = rotmats
                    # tree_data[joint][1] = np.add(pos_values, track.skeleton[joint]['offsets'])
                    tree_data[joint][1] = pos_values
                else:
                    # for every frame i, multiply this joint's rotmat to the rotmat of its parent
                    tree_data[joint][0] = np.asarray([
                        np.matmul(rotmats[i], tree_data[parent][0][i])
                        for i in range(len(tree_data[parent][0]))
                    ])

                    # add the position channel to the offset and store it in k, for every frame i
                    k = np.asarray([
                        np.add(pos_values[i], track.skeleton[joint]['offsets'])
                        for i in range(len(tree_data[parent][0]))
                    ])

                    # multiply k to the rotmat of the parent for every frame i
                    q = np.asarray([
                        np.matmul(k[i], tree_data[parent][0][i])
                        for i in range(len(tree_data[parent][0]))
                    ])

                    # add q to the position of the parent, for every frame i
                    tree_data[joint][1] = np.asarray([
                        np.add(q[i], tree_data[parent][1][i])
                        for i in range(len(tree_data[parent][1]))
                    ])

                # Create the corresponding columns in the new DataFrame
                pos_df['%s_Xposition' % joint] = pd.Series(
                    data=[e[0] for e in tree_data[joint][1]],
                    index=pos_df.index)
                pos_df['%s_Yposition' % joint] = pd.Series(
                    data=[e[1] for e in tree_data[joint][1]],
                    index=pos_df.index)
                pos_df['%s_Zposition' % joint] = pd.Series(
                    data=[e[2] for e in tree_data[joint][1]],
                    index=pos_df.index)

            new_track = track.clone()
            new_track.values = pos_df
            Q.append(new_track)
        return Q