示例#1
0
def _couple_axes(command_dicts):
    """
    If axis 2 and 3 are coupled (as they are with FANUC, for example),
    Modify A3 accordingly
    """
    # Get axes, if they exist
    command_axes = []
    for command_dict in command_dicts:
        axes = command_dict[
            postproc.AXES] if postproc.AXES in command_dict else None
        command_axes.append(list(axes))

    # Make sure the user has selected use of axes
    if not all(x is None for x in command_axes):
        # Get indices for command and axis
        for command_index in range(len(command_dicts)):
            theta_2 = command_axes[command_index][1]
            theta_3 = command_axes[command_index][2]

            theta_3_coupled = theta_3 - theta_2

            # Replace theta_3 in the command_axes list with the coupled value
            command_axes[command_index][2] = theta_3_coupled

            # Replace the original commands with the new commands
            coupled_commands = postproc.Axes(*command_axes[command_index])
            command_dicts[command_index][postproc.AXES] = coupled_commands

    return command_dicts
示例#2
0
def _reconcile_command_rotations(robot_name, command_dicts):
    """
    Check commands that used a sample rate.

    This is primarily used to ensure that rotation is accumulated when an axis
    rotates beyond +/- 180 degrees to avoid discontinuities 

    :param robot_name:
    :param animation_settings:
    :param command_dicts:
    :return:
    """
    # Get axes, if they exist
    command_axes = []
    for command_dict in command_dicts:
        axes = command_dict[
            postproc.AXES] if postproc.AXES in command_dict else None
        command_axes.append(list(axes))

    reconcile_axes = mimic_utils.get_reconcile_axes(robot_name)

    # Make sure the user has selected use of axes
    if not all(x is None for x in command_axes):
        # Get indices for command and axis
        for command_index in range(len(command_dicts)):
            for axis_index in range(6):
                # Get the initial value
                value = command_axes[command_index][axis_index]
                reconcile_axis = reconcile_axes[axis_index]
                # Operate on the value depending on conditional
                if reconcile_axis:
                    if command_index == 0:
                        continue
                    else:  # Perform the check
                        previous_value = command_axes[command_index -
                                                      1][axis_index]
                        value = mimic_utils.accumulate_rotation(
                            value, previous_value)
                    # Replace original value with new value
                    command_axes[command_index][axis_index] = value
                else:  # Not a problem axis
                    pass
            # Replace the original commands with the new commands
            reconciled_axes = postproc.Axes(*command_axes[command_index])
            command_dicts[command_index][postproc.AXES] = reconciled_axes

    return command_dicts
示例#3
0
def _check_command_rotations(robot, animation_settings, command_dicts):
    """
    Check commands that used a sample rate.
    :param robot:
    :param animation_settings:
    :param command_dicts:
    :return:
    """
    # TODO: Do this check using userOptions instead...
    # Get axes, if they exist
    command_axes = []
    for command_dict in command_dicts:
        axes = command_dict[postproc.AXES] if postproc.AXES in command_dict else None
        command_axes.append(list(axes))

    # Make sure the user has selected use of axes
    if not all(x is None for x in command_axes):
        start_frame = animation_settings['Start Frame']
        # Get indices for command and axis
        for command_index in range(len(command_dicts)):
            for axis_index in range(6):
                # Get the initial value
                value = command_axes[command_index][axis_index]
                # Operate on the value depending on conditional
                if axis_index == 3 or axis_index == 5:  # zero-indexed
                    rotation_axis = 'Z'
                    if command_index == 0:  # Get initial value
                        axis_number = axis_index + 1
                        value = mimic_utils.get_reconciled_rotation_value(
                            robot,
                            axis_number,
                            rotation_axis,
                            start_frame)[0]
                    else:  # Perform the check
                        previous_value = command_axes[command_index - 1][axis_index]
                        value = mimic_utils.accumulate_rotation(
                            value,
                            previous_value)
                    # Replace original value with new value
                    command_axes[command_index][axis_index] = value
                else:  # Not a problem axis
                    pass
            # Replace the original commands with the new commands
            reconciled_axes = postproc.Axes(*command_axes[command_index])
            command_dicts[command_index][postproc.AXES] = reconciled_axes
    return command_dicts
示例#4
0
def _sample_frames_get_command_dicts(robot_name, frames, animation_settings,
                                     time_interval_in_seconds, user_options):
    """
    Sample robot commands using a list of frames and user options.
    :param robot_name:
    :param frames:
    :param animation_settings:
    :param user_options:
    :return:
    """
    # Initialize output array.
    command_dicts = []
    time_index_count = 0

    for frame in frames:
        # Set the background to the current frame
        # TODO: Implement this! This rocks:
        # pm.currentTime(frame)
        # Create a dict of datatypes per frame
        command_dict = {}
        # Add this frame number/step/index to the dictionary
        command_dict['Frame'] = frame
        command_dict['Framerate'] = animation_settings['Framerate']
        command_dict[
            'Time Index'] = time_index_count * time_interval_in_seconds
        time_index_count += 1

        # Get motion parameters
        if not user_options.Ignore_motion:
            if user_options.Include_axes:
                axes = _sample_frame_get_axes(robot_name, frame)
                command_dict[postproc.AXES] = postproc.Axes(*axes)
            if user_options.Include_pose:
                pose = _sample_frame_get_pose(robot_name, frame)
                command_dict[postproc.POSE] = postproc.Pose(*pose)
            if user_options.Include_external_axes:
                external_axes = _sample_frame_get_external_axes(
                    robot_name, frame)
                command_dict[postproc.EXTERNAL_AXES] = postproc.ExternalAxes(
                    *external_axes)
            if user_options.Include_configuration:
                configuration = _sample_frame_get_configuration(
                    robot_name, frame)
                command_dict[postproc.CONFIGURATION] = postproc.Configuration(
                    *configuration)
        # Get IO parameters
        if not user_options.Ignore_IOs:
            if user_options.Include_digital_outputs:
                # TODO: Implement digital outputs
                # digital_output = None
                # command_dict[postproc.DIGITAL_OUTPUT] = postproc.DigitalOutput(*digital_output)
                pass
            if user_options.Include_digital_inputs:
                # TODO: Implement digital inputs
                # digital_input = None
                # command_dict[postproc.DIGITAL_INPUT'] = postproc.DigitalOutput(*digital_input)
                pass
            if user_options.Include_analog_outputs:
                # TODO: Implement analog outputs
                # analog_output = None
                # command_dict[postproc.ANALOG_OUTPUT] = postproc.DigitalOutput(*analog_output)
                pass
            if user_options.Include_analog_inputs:
                # TODO: Implement analog inputs
                # analog_input = None
                # command_dict[postproc.ANALOG_INPUT] = postproc.DigitalOutput(*analog_input)
                pass
        command_dicts.append(command_dict)

    # Reset current frame (just in case)
    pm.currentTime(frames[0])
    return command_dicts
示例#5
0
def _bound_accumulated_rotations(robot_name, command_dicts):
    """
    Checks axes whose rotations have been accumulated to ensure they've not 
    exceeded the stated limits. If they have, this function attempts to slide
    the commands by +/- 360 degrees. If the limits are still exceeded, this 
    function returns the commands that exceed the limits by the least amount
    :param robot_name:
    :param animation_settings:
    :param command_dicts:
    :return:
    """
    # TODO: Do this check using userOptions instead...
    # Get axes, if they exist
    command_axes = []
    for command_dict in command_dicts:
        axes = command_dict[
            postproc.AXES] if postproc.AXES in command_dict else None
        command_axes.append(list(axes))

    reconcile_axes = mimic_utils.get_reconcile_axes(robot_name)
    rotation_limits = mimic_utils.get_all_limits(robot_name)['Position']

    # Make sure the user has selected use of axes
    if not all(x is None for x in command_axes):
        for i, reconcile_axis in enumerate(reconcile_axes):
            if reconcile_axis:
                axis_number = i + 1  # Axis numbers are 1-indexed
                axis_name = 'Axis {}'.format(axis_number)

                # Get the axis limits
                limit_min = rotation_limits[axis_name]['Min Limit']
                limit_max = rotation_limits[axis_name]['Max Limit']

                # Create a list of commands for the axis to be checked
                axis_vals_init = [axis[i] for axis in command_axes]

                axis_min = min(axis_vals_init)
                axis_max = max(axis_vals_init)
                '''
                print "#######################################################"
                print "Initial Axis {} vals: ".format(i+1), axis_vals_init
                print "Axis Min Limit: ", limit_min
                print "Axis Max Limit: ", limit_max                
                print "Axis Min: ", axis_min
                print "Axis Max: ", axis_max
                '''

                ## Perform conditional checks
                # If no limits are violated, continue to the next axis without
                # modifying the commands
                if axis_min >= limit_min and axis_max <= limit_max:
                    # print '## No limits exceeded, no shift'
                    continue

                # If both the max and min axis values exceed their respective
                # limits, then there's nothing we can do about it, so we don't
                # modify the commands
                if axis_min < limit_min and axis_max > limit_max:
                    # print '## Both limits exceeded, but no shift'
                    continue

                ## Try bounding the values between the limits by shifting
                ## the commands by +/- 360 degrees

                coeff = -1 if axis_min < limit_min else 1

                # Check if the adjusted values would still violate the limits
                # and if so, only shift them if the violation is smaller
                axis_min_shift = axis_min - (coeff * 360)
                axis_max_shift = axis_max - (coeff * 360)

                # print "Axis Min Shifted: ", axis_min_shift
                # print "Axis Max Shifted: ", axis_max_shift

                if axis_min_shift < limit_min:
                    if abs(axis_min - limit_min) < abs(axis_min_shift -
                                                       limit_min):
                        # print '## Min limit exceeded, but no shift'
                        continue
                elif axis_max_shift > limit_max:
                    if abs(axis_max - limit_max) < abs(axis_max_shift -
                                                       limit_max):
                        # print '## Max limit exceeded, but no shift'
                        continue

                # If we've mad it this far it means we should shift all of the
                # rotation values of the current axis by +/- 360
                # print '## Limit exceeded and values shifted'

                axis_vals_shift = [
                    val - (coeff * 360) for val in axis_vals_init
                ]

                # print "Shifted Axis {} vals: ".format(i+1), axis_vals_shift

                # Drop the shifted values back into the command_dicts
                for command_index in range(len(command_dicts)):
                    command_axes[command_index][i] = axis_vals_shift[
                        command_index]

                    reconciled_axes = postproc.Axes(
                        *command_axes[command_index])
                    command_dicts[command_index][
                        postproc.AXES] = reconciled_axes

    return command_dicts
示例#6
0
def _sample_frames_get_command_dicts(robot_name, frames, animation_settings,
                                     user_options, postproc_settings):
    """
    Sample robot commands using a list of frames and user options.
    :param robot_name:
    :param frames:
    :param animation_settings:
    :param user_options:
    :return:
    """
    # Initialize output array.
    command_dicts = []
    start_frame = animation_settings['Start Frame']
    end_frame = animation_settings['End Frame']

    preview_in_viewport = postproc_settings['Preview in Viewport']

    for frame in frames:

        if preview_in_viewport:
            # Set the background to the current frame
            pm.currentTime(frame)

        # Create a dict of datatypes per frame
        command_dict = {}
        # Add this frame number/step/index to the dictionary
        command_dict['Frame'] = frame
        command_dict['Framerate'] = animation_settings['Framerate']
        command_dict[postproc.TIME_INDEX] = (
            frame - start_frame) / animation_settings['Framerate']

        # Get motion parameters
        if not user_options.Ignore_motion:
            if user_options.Include_axes:
                axes = _sample_frame_get_axes(robot_name, frame)
                command_dict[postproc.AXES] = postproc.Axes(*axes)
            if user_options.Include_pose:
                pose = _sample_frame_get_pose(robot_name, frame)
                command_dict[postproc.POSE] = postproc.Pose(*pose)
            if user_options.Include_external_axes:
                external_axes = _sample_frame_get_external_axes(
                    robot_name, frame)
                command_dict[postproc.EXTERNAL_AXES] = postproc.ExternalAxes(
                    *external_axes)
            if user_options.Include_configuration:
                configuration = _sample_frame_get_configuration(
                    robot_name, frame)
                command_dict[postproc.CONFIGURATION] = postproc.Configuration(
                    *configuration)
        # Get IO parameters
        if not user_options.Ignore_IOs:
            if user_options.Include_digital_outputs:
                digital_output = _sample_frame_get_outs(
                    robot_name, frame, 'digital')
                command_dict[postproc.DIGITAL_OUTPUT] = digital_output
            if user_options.Include_digital_inputs:
                # TODO: Implement digital inputs
                # digital_input = None
                # command_dict[postproc.DIGITAL_INPUT'] = postproc.DigitalOutput(*digital_input)
                pass
            if user_options.Include_analog_outputs:
                analog_output = _sample_frame_get_outs(robot_name, frame,
                                                       'analog')
                command_dict[postproc.ANALOG_OUTPUT] = analog_output
            if user_options.Include_analog_inputs:
                # TODO: Implement analog inputs
                # analog_input = None
                # command_dict[postproc.ANALOG_INPUT] = postproc.DigitalOutput(*analog_input)
                pass
        command_dicts.append(command_dict)
        pm.refresh()
        _update_export_progress_bar(start_frame, end_frame, frame)
    # Reset current frame (just in case)
    pm.currentTime(frames[0])

    return command_dicts
示例#7
0
def _generate_derivative_dicts(command_dicts, order):
    """
    Generate a command dicts list that is the derivitive of the input 
    command_dicts
    :param command_dicts: list formatted by mimic_program containing dicts of
        program info at each program timestep
    :param order: int specifying the order of the derivative (e.g. 1, 2, 3)
    :return derivative_dicts: list containing command dicts for the current
        derivative. Follows the same structure as command_dicts
    """
    import copy
    derivative_dicts = copy.deepcopy(command_dicts)

    num_axes = _get_num_primary_axes(derivative_dicts)
    previous_axes = []

    for command_index, current_command in enumerate(command_dicts):
        current_axes = current_command[postproc.AXES]
        current_axes_derivative = [0] * num_axes
        if command_index > 0:  # skip zeroth
            for axis_index, current_axis in enumerate(current_axes):
                previous_axis = previous_axes[axis_index]

                displacement = current_axis - previous_axis
                # Do we need to compute displacement_time between every frame? Does this change?
                displacement_time = current_command[
                    postproc.TIME_INDEX] - previous_command[
                        postproc.TIME_INDEX]
                derivative = displacement / displacement_time
                current_axes_derivative[axis_index] = derivative

        derivative_dicts[command_index][postproc.AXES] = postproc.Axes(
            *current_axes_derivative)

        previous_axes = current_axes
        previous_command = current_command

    # Replace order-th value with with zeros; this is not a derivitive
    # We do this to ensure the lengths of our command remain constant
    for i in range(order):
        try:
            derivative_dicts[i][postproc.AXES] = postproc.Axes(*[0] * num_axes)
        except IndexError:
            pm.warning('Insufficient number of sample points to generate derivatives. ' \
                       'Increase sample rate or add additional IK/FK keys for proper ' \
                       'analysis if using time-based post-processor')

    # If external axes exist, repeat derivative process on them
    if 'external_axes' in derivative_dicts[0]:
        num_external_axes = len(command_dicts[0][postproc.EXTERNAL_AXES])

        # Get the indeces of external axes that are being used
        active_axes = [
            i
            for i, x in enumerate(derivative_dicts[0][postproc.EXTERNAL_AXES])
            if not x is None
        ]

        num_active_external_axes = len(active_axes)
        previous_axes = []

        for command_index, current_command in enumerate(command_dicts):
            current_axes = [
                current_command[postproc.EXTERNAL_AXES][x] for x in active_axes
            ]
            current_axes_derivative = [0] * num_active_external_axes

            if command_index > 0:  # skip zeroth
                for derivative_index, current_axis in enumerate(current_axes):
                    previous_axis = previous_axes[derivative_index]
                    displacement = current_axis - previous_axis
                    displacement_time = current_command[
                        postproc.TIME_INDEX] - previous_command[
                            postproc.TIME_INDEX]
                    derivative = displacement / displacement_time
                    current_axes_derivative[derivative_index] = derivative

            # We have to pass the same amount of axes that are in the
            # Postprocess EXTERNAL_AXIS structure, so we have to build an array
            # That matches the number of axis, with 'None' values for
            # inactive axes.
            external_axis_derivatives = [None] * num_external_axes

            for derivative_index, axis_index in enumerate(active_axes):
                external_axis_derivatives[
                    axis_index] = current_axes_derivative[derivative_index]

            # Replace the current command entry with the command's derivatives
            derivative_dicts[command_index][
                postproc.EXTERNAL_AXES] = postproc.ExternalAxes(
                    *external_axis_derivatives)

            previous_axes = current_axes
            previous_command = current_command

        # Replace order-th value with with zeros; this is not a derivitive
        # We do this to ensure the lengths of our command remain constant
        axis_pop = [None] * num_external_axes
        for a, _ in enumerate(axis_pop):
            if not derivative_dicts[i][postproc.EXTERNAL_AXES][a] is None:
                axis_pop[a] = 0

        for i in range(order):
            derivative_dicts[i][
                postproc.EXTERNAL_AXES] = postproc.ExternalAxes(*axis_pop)

    return derivative_dicts