src/bvhtoolbox/manipulate/offsetjointangles.py
def add_angle_offsets(bvh_tree, angle_offsets):
    """Add rotation to joints in bvh_tree.

    :param bvh_tree: BVH structure
    :type bvh_tree: bvhtree.BvhTree
    :param angle_offsets: A dictionary containing joint names as keys and euler angles in degrees as values.
    The order of the euler angles needs to be the same as the channel order for this joint in the BVH file.
    If not all 3 rotation channels are present for a joint, the missing channels will get appended.
    :type angle_offsets: dict
    """
    if not angle_offsets:
        print("WARNING: No rotation offsets. Aborting.")
        return
    
    frames = get_motion_data(bvh_tree)
    # Convert the given euler angles to quaternions.
    for joint_name, angle_values in angle_offsets.items():
        try:
            joint = bvh_tree.get_joint(joint_name)
        except LookupError:
            print("WARNING: joint {} not found.".format(joint_name))
            continue
            
        channel_names = bvh_tree.joint_channels(joint_name)
        # Find CHANNELS BvhNode.
        channel_node = joint.children[1]
        for channel in ['Xrotation', 'Yrotation', 'Zrotation']:
            if channel not in channel_names:
                channel_names.append(channel)
                # Joint gets a new channel
                channel_node.value.append(channel)
                channel_node.value[1] = str(int(channel_node.value[1]) + 1)
                # Insert new channel into frames.
                insert_idx = bvh_tree.get_joint_channels_index(joint_name) + bvh_tree.get_joint_channel_index(joint_name, channel)
                frames = np.insert(frames, insert_idx, 0.0, axis=1)  # Initialize with 0.
        channel_order = 's' + ''.join([channel[:1].lower() for channel in channel_names if channel.endswith("rotation")])
        angle_offset_quat = t3d.euler.euler2quat(*np.radians(angle_values), axes=channel_order)
        joint_angles = get_quaternions(bvh_tree, joint_name, axes=channel_order)
        new_angles = np.degrees([t3d.euler.quat2euler(t3d.quaternions.qmult(q, angle_offset_quat), axes=channel_order) for q in joint_angles])
        # Replace frames with new values.
        channels_idx = bvh_tree.get_joint_channels_index(joint_name)
        rot_channels_idx = channels_idx + bvh_tree.get_joint_channel_index(joint_name, channel_names[0])
        frames[:, rot_channels_idx: rot_channels_idx+3] = new_angles
    set_motion_data(bvh_tree, frames)
Add rotation to joints in bvh_tree.

    :param bvh_tree: BVH structure
    :type bvh_tree: bvhtree.BvhTree
    :param angle_offsets: A dictionary containing joint names as keys and euler angles in degrees as values.
    The order of the euler angles needs to be the same as the channel order for this joint in the BVH file.
    If not all 3 rotation channels are present for a joint, the missing channels will get appended.
    :type angle_offsets: dict
    
Add rotation to joints in bvh_tree.
Add rotation to joints in bvh_tree .
def add_angle_offsets(bvh_tree, angle_offsets):
    if not angle_offsets:
        print("WARNING: No rotation offsets. Aborting.")
        return
    frames = get_motion_data(bvh_tree)
    for joint_name, angle_values in angle_offsets.items():
        try:
            joint = bvh_tree.get_joint(joint_name)
        except LookupError:
            print("WARNING: joint {} not found.".format(joint_name))
            continue
        channel_names = bvh_tree.joint_channels(joint_name)
        channel_node = joint.children[1]
        for channel in ['Xrotation', 'Yrotation', 'Zrotation']:
            if channel not in channel_names:
                channel_names.append(channel)
                channel_node.value.append(channel)
                channel_node.value[1] = str(int(channel_node.value[1]) + 1)
                insert_idx = bvh_tree.get_joint_channels_index(joint_name) + bvh_tree.get_joint_channel_index(joint_name, channel)
                frames = np.insert(frames, insert_idx, 0.0, axis=1)  
        channel_order = 's' + ''.join([channel[:1].lower() for channel in channel_names if channel.endswith("rotation")])
        angle_offset_quat = t3d.euler.euler2quat(*np.radians(angle_values), axes=channel_order)
        joint_angles = get_quaternions(bvh_tree, joint_name, axes=channel_order)
        new_angles = np.degrees([t3d.euler.quat2euler(t3d.quaternions.qmult(q, angle_offset_quat), axes=channel_order) for q in joint_angles])
        channels_idx = bvh_tree.get_joint_channels_index(joint_name)
        rot_channels_idx = channels_idx + bvh_tree.get_joint_channel_index(joint_name, channel_names[0])
        frames[:, rot_channels_idx: rot_channels_idx+3] = new_angles
    set_motion_data(bvh_tree, frames)
def add_angle_offsets ( bvh_tree , angle_offsets ) : if not angle_offsets : print ( "WARNING: No rotation offsets. Aborting." ) return frames = get_motion_data ( bvh_tree ) for joint_name , angle_values in angle_offsets . items ( ) : try : joint = bvh_tree . get_joint ( joint_name ) except LookupError : print ( "WARNING: joint {} not found." . format ( joint_name ) ) continue channel_names = bvh_tree . joint_channels ( joint_name ) channel_node = joint . children [ 1 ] for channel in [ 'Xrotation' , 'Yrotation' , 'Zrotation' ] : if channel not in channel_names : channel_names . append ( channel ) channel_node . value . append ( channel ) channel_node . value [ 1 ] = str ( int ( channel_node . value [ 1 ] ) + 1 ) insert_idx = bvh_tree . get_joint_channels_index ( joint_name ) + bvh_tree . get_joint_channel_index ( joint_name , channel ) frames = np . insert ( frames , insert_idx , 0.0 , axis = 1 ) channel_order = 's' + '' . join ( [ channel [ : 1 ] . lower ( ) for channel in channel_names if channel . endswith ( "rotation" ) ] ) angle_offset_quat = t3d . euler . euler2quat ( * np . radians ( angle_values ) , axes = channel_order ) joint_angles = get_quaternions ( bvh_tree , joint_name , axes = channel_order ) new_angles = np . degrees ( [ t3d . euler . quat2euler ( t3d . quaternions . qmult ( q , angle_offset_quat ) , axes = channel_order ) for q in joint_angles ] ) channels_idx = bvh_tree . get_joint_channels_index ( joint_name ) rot_channels_idx = channels_idx + bvh_tree . get_joint_channel_index ( joint_name , channel_names [ 0 ] ) frames [ : , rot_channels_idx : rot_channels_idx + 3 ] = new_angles set_motion_data ( bvh_tree , frames )
Add rotation to joints in bvh_tree.
Add rotation to joints in bvh_tree .
"""Add rotation to joints in bvh_tree.

    :param bvh_tree: BVH structure
    :type bvh_tree: bvhtree.BvhTree
    :param angle_offsets: A dictionary containing joint names as keys and euler angles in degrees as values.
    The order of the euler angles needs to be the same as the channel order for this joint in the BVH file.
    If not all 3 rotation channels are present for a joint, the missing channels will get appended.
    :type angle_offsets: dict
    """ # Convert the given euler angles to quaternions. # Find CHANNELS BvhNode. # Joint gets a new channel # Insert new channel into frames. # Initialize with 0. # Replace frames with new values.
bvh_tree
None
angle_offsets
A dictionary containing joint names as keys and euler angles in degrees as values.
The order of the euler angles needs to be the same as the channel order for this joint in the BVH file.
If not all 3 rotation channels are present for a joint, the missing channels will get appended.
A dictionary containing joint names as keys and euler angles in degrees as values . The order of the euler angles needs to be the same as the channel order for this joint in the BVH file . If not all 3 rotation channels are present for a joint the missing channels will get appended .